1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * fs.c filesystem APIs
3*de1e4e89SAndroid Build Coastguard Worker *
4*de1e4e89SAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker * modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker * as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker * 2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker *
9*de1e4e89SAndroid Build Coastguard Worker * Authors: David Ahern <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker *
11*de1e4e89SAndroid Build Coastguard Worker */
12*de1e4e89SAndroid Build Coastguard Worker
13*de1e4e89SAndroid Build Coastguard Worker #include <sys/types.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <sys/stat.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <sys/mount.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <ctype.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
21*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
22*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
23*de1e4e89SAndroid Build Coastguard Worker #include <errno.h>
24*de1e4e89SAndroid Build Coastguard Worker #include <limits.h>
25*de1e4e89SAndroid Build Coastguard Worker
26*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
27*de1e4e89SAndroid Build Coastguard Worker
28*de1e4e89SAndroid Build Coastguard Worker #define CGROUP2_FS_NAME "cgroup2"
29*de1e4e89SAndroid Build Coastguard Worker
30*de1e4e89SAndroid Build Coastguard Worker /* if not already mounted cgroup2 is mounted here for iproute2's use */
31*de1e4e89SAndroid Build Coastguard Worker #define MNT_CGRP2_PATH "/var/run/cgroup2"
32*de1e4e89SAndroid Build Coastguard Worker
33*de1e4e89SAndroid Build Coastguard Worker /* return mount path of first occurrence of given fstype */
find_fs_mount(const char * fs_to_find)34*de1e4e89SAndroid Build Coastguard Worker static char *find_fs_mount(const char *fs_to_find)
35*de1e4e89SAndroid Build Coastguard Worker {
36*de1e4e89SAndroid Build Coastguard Worker char path[4096];
37*de1e4e89SAndroid Build Coastguard Worker char fstype[128]; /* max length of any filesystem name */
38*de1e4e89SAndroid Build Coastguard Worker char *mnt = NULL;
39*de1e4e89SAndroid Build Coastguard Worker FILE *fp;
40*de1e4e89SAndroid Build Coastguard Worker
41*de1e4e89SAndroid Build Coastguard Worker fp = fopen("/proc/mounts", "r");
42*de1e4e89SAndroid Build Coastguard Worker if (!fp) {
43*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
44*de1e4e89SAndroid Build Coastguard Worker "Failed to open mounts file: %s\n", strerror(errno));
45*de1e4e89SAndroid Build Coastguard Worker return NULL;
46*de1e4e89SAndroid Build Coastguard Worker }
47*de1e4e89SAndroid Build Coastguard Worker
48*de1e4e89SAndroid Build Coastguard Worker while (fscanf(fp, "%*s %4095s %127s %*s %*d %*d\n",
49*de1e4e89SAndroid Build Coastguard Worker path, fstype) == 2) {
50*de1e4e89SAndroid Build Coastguard Worker if (strcmp(fstype, fs_to_find) == 0) {
51*de1e4e89SAndroid Build Coastguard Worker mnt = strdup(path);
52*de1e4e89SAndroid Build Coastguard Worker break;
53*de1e4e89SAndroid Build Coastguard Worker }
54*de1e4e89SAndroid Build Coastguard Worker }
55*de1e4e89SAndroid Build Coastguard Worker
56*de1e4e89SAndroid Build Coastguard Worker fclose(fp);
57*de1e4e89SAndroid Build Coastguard Worker
58*de1e4e89SAndroid Build Coastguard Worker return mnt;
59*de1e4e89SAndroid Build Coastguard Worker }
60*de1e4e89SAndroid Build Coastguard Worker
61*de1e4e89SAndroid Build Coastguard Worker /* caller needs to free string returned */
find_cgroup2_mount(void)62*de1e4e89SAndroid Build Coastguard Worker char *find_cgroup2_mount(void)
63*de1e4e89SAndroid Build Coastguard Worker {
64*de1e4e89SAndroid Build Coastguard Worker char *mnt = find_fs_mount(CGROUP2_FS_NAME);
65*de1e4e89SAndroid Build Coastguard Worker
66*de1e4e89SAndroid Build Coastguard Worker if (mnt)
67*de1e4e89SAndroid Build Coastguard Worker return mnt;
68*de1e4e89SAndroid Build Coastguard Worker
69*de1e4e89SAndroid Build Coastguard Worker mnt = strdup(MNT_CGRP2_PATH);
70*de1e4e89SAndroid Build Coastguard Worker if (!mnt) {
71*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Failed to allocate memory for cgroup2 path\n");
72*de1e4e89SAndroid Build Coastguard Worker return NULL;
73*de1e4e89SAndroid Build Coastguard Worker
74*de1e4e89SAndroid Build Coastguard Worker }
75*de1e4e89SAndroid Build Coastguard Worker
76*de1e4e89SAndroid Build Coastguard Worker if (make_path(mnt, 0755)) {
77*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Failed to setup vrf cgroup2 directory\n");
78*de1e4e89SAndroid Build Coastguard Worker free(mnt);
79*de1e4e89SAndroid Build Coastguard Worker return NULL;
80*de1e4e89SAndroid Build Coastguard Worker }
81*de1e4e89SAndroid Build Coastguard Worker
82*de1e4e89SAndroid Build Coastguard Worker if (mount("none", mnt, CGROUP2_FS_NAME, 0, NULL)) {
83*de1e4e89SAndroid Build Coastguard Worker /* EBUSY means already mounted */
84*de1e4e89SAndroid Build Coastguard Worker if (errno == EBUSY)
85*de1e4e89SAndroid Build Coastguard Worker goto out;
86*de1e4e89SAndroid Build Coastguard Worker
87*de1e4e89SAndroid Build Coastguard Worker if (errno == ENODEV) {
88*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
89*de1e4e89SAndroid Build Coastguard Worker "Failed to mount cgroup2. Are CGROUPS enabled in your kernel?\n");
90*de1e4e89SAndroid Build Coastguard Worker } else {
91*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
92*de1e4e89SAndroid Build Coastguard Worker "Failed to mount cgroup2: %s\n",
93*de1e4e89SAndroid Build Coastguard Worker strerror(errno));
94*de1e4e89SAndroid Build Coastguard Worker }
95*de1e4e89SAndroid Build Coastguard Worker free(mnt);
96*de1e4e89SAndroid Build Coastguard Worker return NULL;
97*de1e4e89SAndroid Build Coastguard Worker }
98*de1e4e89SAndroid Build Coastguard Worker out:
99*de1e4e89SAndroid Build Coastguard Worker return mnt;
100*de1e4e89SAndroid Build Coastguard Worker }
101*de1e4e89SAndroid Build Coastguard Worker
make_path(const char * path,mode_t mode)102*de1e4e89SAndroid Build Coastguard Worker int make_path(const char *path, mode_t mode)
103*de1e4e89SAndroid Build Coastguard Worker {
104*de1e4e89SAndroid Build Coastguard Worker char *dir, *delim;
105*de1e4e89SAndroid Build Coastguard Worker int rc = -1;
106*de1e4e89SAndroid Build Coastguard Worker
107*de1e4e89SAndroid Build Coastguard Worker delim = dir = strdup(path);
108*de1e4e89SAndroid Build Coastguard Worker if (dir == NULL) {
109*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "strdup failed copying path");
110*de1e4e89SAndroid Build Coastguard Worker return -1;
111*de1e4e89SAndroid Build Coastguard Worker }
112*de1e4e89SAndroid Build Coastguard Worker
113*de1e4e89SAndroid Build Coastguard Worker /* skip '/' -- it had better exist */
114*de1e4e89SAndroid Build Coastguard Worker if (*delim == '/')
115*de1e4e89SAndroid Build Coastguard Worker delim++;
116*de1e4e89SAndroid Build Coastguard Worker
117*de1e4e89SAndroid Build Coastguard Worker while (1) {
118*de1e4e89SAndroid Build Coastguard Worker delim = strchr(delim, '/');
119*de1e4e89SAndroid Build Coastguard Worker if (delim)
120*de1e4e89SAndroid Build Coastguard Worker *delim = '\0';
121*de1e4e89SAndroid Build Coastguard Worker
122*de1e4e89SAndroid Build Coastguard Worker rc = mkdir(dir, mode);
123*de1e4e89SAndroid Build Coastguard Worker if (mkdir(dir, mode) != 0 && errno != EEXIST) {
124*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "mkdir failed for %s: %s\n",
125*de1e4e89SAndroid Build Coastguard Worker dir, strerror(errno));
126*de1e4e89SAndroid Build Coastguard Worker goto out;
127*de1e4e89SAndroid Build Coastguard Worker }
128*de1e4e89SAndroid Build Coastguard Worker
129*de1e4e89SAndroid Build Coastguard Worker if (delim == NULL)
130*de1e4e89SAndroid Build Coastguard Worker break;
131*de1e4e89SAndroid Build Coastguard Worker
132*de1e4e89SAndroid Build Coastguard Worker *delim = '/';
133*de1e4e89SAndroid Build Coastguard Worker delim++;
134*de1e4e89SAndroid Build Coastguard Worker if (*delim == '\0')
135*de1e4e89SAndroid Build Coastguard Worker break;
136*de1e4e89SAndroid Build Coastguard Worker }
137*de1e4e89SAndroid Build Coastguard Worker rc = 0;
138*de1e4e89SAndroid Build Coastguard Worker out:
139*de1e4e89SAndroid Build Coastguard Worker free(dir);
140*de1e4e89SAndroid Build Coastguard Worker
141*de1e4e89SAndroid Build Coastguard Worker return rc;
142*de1e4e89SAndroid Build Coastguard Worker }
143*de1e4e89SAndroid Build Coastguard Worker
get_command_name(const char * pid,char * comm,size_t len)144*de1e4e89SAndroid Build Coastguard Worker int get_command_name(const char *pid, char *comm, size_t len)
145*de1e4e89SAndroid Build Coastguard Worker {
146*de1e4e89SAndroid Build Coastguard Worker char path[PATH_MAX];
147*de1e4e89SAndroid Build Coastguard Worker char line[128];
148*de1e4e89SAndroid Build Coastguard Worker FILE *fp;
149*de1e4e89SAndroid Build Coastguard Worker
150*de1e4e89SAndroid Build Coastguard Worker if (snprintf(path, sizeof(path),
151*de1e4e89SAndroid Build Coastguard Worker "/proc/%s/status", pid) >= sizeof(path)) {
152*de1e4e89SAndroid Build Coastguard Worker return -1;
153*de1e4e89SAndroid Build Coastguard Worker }
154*de1e4e89SAndroid Build Coastguard Worker
155*de1e4e89SAndroid Build Coastguard Worker fp = fopen(path, "r");
156*de1e4e89SAndroid Build Coastguard Worker if (!fp)
157*de1e4e89SAndroid Build Coastguard Worker return -1;
158*de1e4e89SAndroid Build Coastguard Worker
159*de1e4e89SAndroid Build Coastguard Worker comm[0] = '\0';
160*de1e4e89SAndroid Build Coastguard Worker while (fgets(line, sizeof(line), fp)) {
161*de1e4e89SAndroid Build Coastguard Worker char *nl, *name;
162*de1e4e89SAndroid Build Coastguard Worker
163*de1e4e89SAndroid Build Coastguard Worker name = strstr(line, "Name:");
164*de1e4e89SAndroid Build Coastguard Worker if (!name)
165*de1e4e89SAndroid Build Coastguard Worker continue;
166*de1e4e89SAndroid Build Coastguard Worker
167*de1e4e89SAndroid Build Coastguard Worker name += 5;
168*de1e4e89SAndroid Build Coastguard Worker while (isspace(*name))
169*de1e4e89SAndroid Build Coastguard Worker name++;
170*de1e4e89SAndroid Build Coastguard Worker
171*de1e4e89SAndroid Build Coastguard Worker nl = strchr(name, '\n');
172*de1e4e89SAndroid Build Coastguard Worker if (nl)
173*de1e4e89SAndroid Build Coastguard Worker *nl = '\0';
174*de1e4e89SAndroid Build Coastguard Worker
175*de1e4e89SAndroid Build Coastguard Worker strlcpy(comm, name, len);
176*de1e4e89SAndroid Build Coastguard Worker break;
177*de1e4e89SAndroid Build Coastguard Worker }
178*de1e4e89SAndroid Build Coastguard Worker
179*de1e4e89SAndroid Build Coastguard Worker fclose(fp);
180*de1e4e89SAndroid Build Coastguard Worker
181*de1e4e89SAndroid Build Coastguard Worker return 0;
182*de1e4e89SAndroid Build Coastguard Worker }
183