1 #define _GNU_SOURCE
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <stdint.h>
8 #include <ctype.h>
9 #include <unistd.h>
10 #include <linux/magic.h>
11 #include <sys/vfs.h>
12 #include <string.h>
13 #include <errno.h>
14
15 /* 67e9c74b8a873408c27ac9a8e4c1d1c8d72c93ff (4.5) */
16 #ifndef CGROUP2_SUPER_MAGIC
17 #define CGROUP2_SUPER_MAGIC 0x63677270
18 #endif
19
20 struct cgid_file_handle
21 {
22 //struct file_handle handle;
23 unsigned int handle_bytes;
24 int handle_type;
25 uint64_t cgid;
26 };
27
get_cgroupid(const char * pathname)28 uint64_t get_cgroupid(const char *pathname) {
29 struct statfs fs;
30 int err;
31 struct cgid_file_handle *h;
32 int mount_id;
33 uint64_t ret;
34
35 err = statfs(pathname, &fs);
36 if (err != 0) {
37 fprintf (stderr, "statfs on %s failed: %s\n", pathname, strerror(errno));
38 exit(1);
39 }
40
41 if ((fs.f_type != (typeof(fs.f_type)) CGROUP2_SUPER_MAGIC)) {
42 fprintf (stderr, "File %s is not on a cgroup2 mount.\n", pathname);
43 exit(1);
44 }
45
46 h = malloc(sizeof(struct cgid_file_handle));
47 if (!h) {
48 fprintf (stderr, "Cannot allocate memory.\n");
49 exit(1);
50 }
51
52 h->handle_bytes = 8;
53 err = name_to_handle_at(AT_FDCWD, pathname, (struct file_handle *)h, &mount_id, 0);
54 if (err != 0) {
55 fprintf (stderr, "name_to_handle_at failed: %s\n", strerror(errno));
56 exit(1);
57 }
58
59 if (h->handle_bytes != 8) {
60 fprintf (stderr, "Unexpected handle size: %d. \n", h->handle_bytes);
61 exit(1);
62 }
63
64 ret = h->cgid;
65 free(h);
66
67 return ret;
68 }
69
usage()70 void usage() {
71 fprintf (stderr, "Usage: cgroupid FORMAT FILE\n");
72 fprintf (stderr, "Print the cgroup id of a cgroup2 directory.\n");
73 fprintf (stderr, "Example: cgroupid print-hex /sys/fs/cgroup/unified/system.slice/test.service\n");
74 fprintf (stderr, "\n");
75 fprintf (stderr, "Format:\n");
76 fprintf (stderr, " number print the cgroup id as a number\n");
77 fprintf (stderr, " hex print the cgroup id as a hexadecimal, suitable for bpftool\n");
78 fprintf (stderr, "\n");
79 }
80
main(int argc,char ** argv)81 int main(int argc, char **argv) {
82 uint64_t cgroupid;
83 int i;
84
85 if (argc != 3 || (strcmp(argv[1], "number") != 0 && strcmp(argv[1], "hex"))) {
86 usage();
87 exit(1);
88 }
89
90 cgroupid = get_cgroupid(argv[2]);
91
92 if (strcmp(argv[1], "number") == 0)
93 printf("%lu\n", cgroupid);
94
95 if (strcmp(argv[1], "hex") == 0) {
96 for (i=0; i<8; i++) {
97 printf("%02x%s", ((unsigned char *)&cgroupid)[i], i == 7 ? "\n":" ");
98 }
99 }
100 return 0;
101 }
102