]>
git.proxmox.com Git - mirror_iproute2.git/blob - lib/fs.c
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: David Ahern <dsa@cumulusnetworks.com>
13 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <sys/mount.h>
28 #define CGROUP2_FS_NAME "cgroup2"
30 /* if not already mounted cgroup2 is mounted here for iproute2's use */
31 #define MNT_CGRP2_PATH "/var/run/cgroup2"
33 /* return mount path of first occurrence of given fstype */
34 static char *find_fs_mount(const char *fs_to_find
)
37 char fstype
[128]; /* max length of any filesystem name */
41 fp
= fopen("/proc/mounts", "r");
44 "Failed to open mounts file: %s\n", strerror(errno
));
48 while (fscanf(fp
, "%*s %4095s %127s %*s %*d %*d\n",
50 if (strcmp(fstype
, fs_to_find
) == 0) {
61 /* caller needs to free string returned */
62 char *find_cgroup2_mount(bool do_mount
)
64 char *mnt
= find_fs_mount(CGROUP2_FS_NAME
);
70 fprintf(stderr
, "Failed to find cgroup2 mount\n");
74 mnt
= strdup(MNT_CGRP2_PATH
);
76 fprintf(stderr
, "Failed to allocate memory for cgroup2 path\n");
81 if (make_path(mnt
, 0755)) {
82 fprintf(stderr
, "Failed to setup cgroup2 directory\n");
87 if (mount("none", mnt
, CGROUP2_FS_NAME
, 0, NULL
)) {
88 /* EBUSY means already mounted */
92 if (errno
== ENODEV
) {
94 "Failed to mount cgroup2. Are CGROUPS enabled in your kernel?\n");
97 "Failed to mount cgroup2: %s\n",
107 __u64
get_cgroup2_id(const char *path
)
109 char fh_buf
[sizeof(struct file_handle
) + sizeof(__u64
)] = { 0 };
110 struct file_handle
*fhp
= (struct file_handle
*)fh_buf
;
113 unsigned char bytes
[sizeof(__u64
)];
114 } cg_id
= { .id
= 0 };
120 fprintf(stderr
, "Invalid cgroup2 path\n");
124 fhp
->handle_bytes
= sizeof(__u64
);
125 if (name_to_handle_at(AT_FDCWD
, path
, fhp
, &mnt_id
, 0) < 0) {
126 /* try at cgroup2 mount */
131 fprintf(stderr
, "Invalid cgroup2 path\n");
135 mnt
= find_cgroup2_mount(false);
139 mnt_fd
= open(mnt
, O_RDONLY
);
141 fprintf(stderr
, "Failed to open cgroup2 mount\n");
145 fhp
->handle_bytes
= sizeof(__u64
);
146 if (name_to_handle_at(mnt_fd
, path
, fhp
, &mnt_id
, 0) < 0) {
147 fprintf(stderr
, "Failed to get cgroup2 ID: %s\n",
152 if (fhp
->handle_bytes
!= sizeof(__u64
)) {
153 fprintf(stderr
, "Invalid size of cgroup2 ID\n");
157 memcpy(cg_id
.bytes
, fhp
->f_handle
, sizeof(__u64
));
167 #define FILEID_INO32_GEN 1
169 /* caller needs to free string returned */
170 char *get_cgroup2_path(__u64 id
, bool full
)
172 char fh_buf
[sizeof(struct file_handle
) + sizeof(__u64
)] = { 0 };
173 struct file_handle
*fhp
= (struct file_handle
*)fh_buf
;
176 unsigned char bytes
[sizeof(__u64
)];
177 } cg_id
= { .id
= id
};
178 int mnt_fd
= -1, fd
= -1;
179 char link_buf
[PATH_MAX
];
186 fprintf(stderr
, "Invalid cgroup2 ID\n");
190 mnt
= find_cgroup2_mount(false);
194 mnt_fd
= open(mnt
, O_RDONLY
);
196 fprintf(stderr
, "Failed to open cgroup2 mount\n");
200 fhp
->handle_bytes
= sizeof(__u64
);
201 fhp
->handle_type
= FILEID_INO32_GEN
;
202 memcpy(fhp
->f_handle
, cg_id
.bytes
, sizeof(__u64
));
204 fd
= open_by_handle_at(mnt_fd
, fhp
, 0);
206 fprintf(stderr
, "Failed to open cgroup2 by ID\n");
210 snprintf(fd_path
, sizeof(fd_path
), "/proc/self/fd/%d", fd
);
211 link_len
= readlink(fd_path
, link_buf
, sizeof(link_buf
) - 1);
214 "Failed to read value of symbolic link %s\n",
218 link_buf
[link_len
] = '\0';
221 path
= strdup(link_buf
);
223 path
= strdup(link_buf
+ strlen(mnt
));
226 "Failed to allocate memory for cgroup2 path\n");
238 int make_path(const char *path
, mode_t mode
)
243 delim
= dir
= strdup(path
);
245 fprintf(stderr
, "strdup failed copying path");
249 /* skip '/' -- it had better exist */
254 delim
= strchr(delim
, '/');
258 rc
= mkdir(dir
, mode
);
259 if (rc
&& errno
!= EEXIST
) {
260 fprintf(stderr
, "mkdir failed for %s: %s\n",
261 dir
, strerror(errno
));
280 int get_command_name(const char *pid
, char *comm
, size_t len
)
286 if (snprintf(path
, sizeof(path
),
287 "/proc/%s/status", pid
) >= sizeof(path
)) {
291 fp
= fopen(path
, "r");
296 while (fgets(line
, sizeof(line
), fp
)) {
299 name
= strstr(line
, "Name:");
304 while (isspace(*name
))
307 nl
= strchr(name
, '\n');
311 strlcpy(comm
, name
, len
);