]> git.proxmox.com Git - mirror_lxcfs.git/blob - src/sysfs_fuse.c
sysfs_fuse: remove logically dead code
[mirror_lxcfs.git] / src / sysfs_fuse.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #ifndef _GNU_SOURCE
4 #define _GNU_SOURCE
5 #endif
6
7 #ifndef FUSE_USE_VERSION
8 #define FUSE_USE_VERSION 26
9 #endif
10
11 #define _FILE_OFFSET_BITS 64
12
13 #define __STDC_FORMAT_MACROS
14 #include <dirent.h>
15 #include <errno.h>
16 #include <fcntl.h>
17 #include <fuse.h>
18 #include <inttypes.h>
19 #include <libgen.h>
20 #include <pthread.h>
21 #include <sched.h>
22 #include <stdbool.h>
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <time.h>
28 #include <unistd.h>
29 #include <wait.h>
30 #include <linux/magic.h>
31 #include <linux/sched.h>
32 #include <sys/epoll.h>
33 #include <sys/mman.h>
34 #include <sys/mount.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37 #include <sys/syscall.h>
38 #include <sys/sysinfo.h>
39 #include <sys/vfs.h>
40
41 #include "bindings.h"
42 #include "memory_utils.h"
43 #include "cgroups/cgroup.h"
44 #include "config.h"
45 #include "sysfs_fuse.h"
46 #include "utils.h"
47
48 static int sys_devices_system_cpu_online_read(char *buf, size_t size,
49 off_t offset,
50 struct fuse_file_info *fi)
51 {
52 __do_free char *cg = NULL, *cpuset = NULL;
53 struct fuse_context *fc = fuse_get_context();
54 struct lxcfs_opts *opts = (struct lxcfs_opts *)fc->private_data;
55 struct file_info *d = INTTYPE_TO_PTR(fi->fh);
56 char *cache = d->buf;
57 bool use_view;
58
59 int max_cpus = 0;
60 pid_t initpid;
61 ssize_t total_len = 0;
62
63 if (offset) {
64 int left;
65
66 if (!d->cached)
67 return 0;
68
69 if (offset > d->size)
70 return -EINVAL;
71
72 left = d->size - offset;
73 total_len = left > size ? size : left;
74 memcpy(buf, cache + offset, total_len);
75
76 return total_len;
77 }
78
79 initpid = lookup_initpid_in_store(fc->pid);
80 if (initpid <= 1 || is_shared_pidns(initpid))
81 initpid = fc->pid;
82
83 cg = get_pid_cgroup(initpid, "cpuset");
84 if (!cg)
85 return read_file_fuse("/sys/devices/system/cpu/online", buf, size, d);
86 prune_init_slice(cg);
87
88 cpuset = get_cpuset(cg);
89 if (!cpuset)
90 return 0;
91
92 if (cgroup_ops->can_use_cpuview(cgroup_ops) && opts && opts->use_cfs)
93 use_view = true;
94 else
95 use_view = false;
96 if (use_view)
97 max_cpus = max_cpu_count(cg);
98
99 if (use_view) {
100 if (max_cpus > 1)
101 total_len = snprintf(d->buf, d->buflen, "0-%d\n", max_cpus - 1);
102 else
103 total_len = snprintf(d->buf, d->buflen, "0\n");
104 } else {
105 total_len = snprintf(d->buf, d->buflen, "%s\n", cpuset);
106 }
107 if (total_len < 0 || total_len >= d->buflen)
108 return log_error(0, "Failed to write to cache");
109
110 d->size = (int)total_len;
111 d->cached = 1;
112
113 if (total_len > size)
114 total_len = size;
115
116 memcpy(buf, d->buf, total_len);
117
118 return total_len;
119 }
120
121 static off_t get_sysfile_size(const char *which)
122 {
123 __do_fclose FILE *f = NULL;
124 __do_free char *line = NULL;
125 size_t len = 0;
126 ssize_t sz, answer = 0;
127
128 f = fopen(which, "re");
129 if (!f)
130 return 0;
131
132 while ((sz = getline(&line, &len, f)) != -1)
133 answer += sz;
134
135 return answer;
136 }
137
138 __lxcfs_fuse_ops int sys_getattr(const char *path, struct stat *sb)
139 {
140 struct timespec now;
141
142 memset(sb, 0, sizeof(struct stat));
143 if (clock_gettime(CLOCK_REALTIME, &now) < 0)
144 return -EINVAL;
145
146 sb->st_uid = sb->st_gid = 0;
147 sb->st_atim = sb->st_mtim = sb->st_ctim = now;
148 if (strcmp(path, "/sys") == 0) {
149 sb->st_mode = S_IFDIR | 00555;
150 sb->st_nlink = 2;
151 return 0;
152 }
153
154 if (strcmp(path, "/sys/devices") == 0) {
155 sb->st_mode = S_IFDIR | 00555;
156 sb->st_nlink = 2;
157 return 0;
158 }
159
160 if (strcmp(path, "/sys/devices/system") == 0) {
161 sb->st_mode = S_IFDIR | 00555;
162 sb->st_nlink = 2;
163 return 0;
164 }
165
166 if (strcmp(path, "/sys/devices/system/cpu") == 0) {
167 sb->st_mode = S_IFDIR | 00555;
168 sb->st_nlink = 2;
169 return 0;
170 }
171
172 if (strcmp(path, "/sys/devices/system/cpu/online") == 0) {
173 sb->st_size = 0;
174 sb->st_mode = S_IFREG | 00444;
175 sb->st_nlink = 1;
176 return 0;
177 }
178
179 return -ENOENT;
180 }
181
182 __lxcfs_fuse_ops int sys_readdir(const char *path, void *buf,
183 fuse_fill_dir_t filler, off_t offset,
184 struct fuse_file_info *fi)
185 {
186 if (strcmp(path, "/sys") == 0) {
187 if (filler(buf, ".", NULL, 0) != 0 ||
188 filler(buf, "..", NULL, 0) != 0 ||
189 filler(buf, "devices", NULL, 0) != 0)
190 return -ENOENT;
191
192 return 0;
193 }
194 if (strcmp(path, "/sys/devices") == 0) {
195 if (filler(buf, ".", NULL, 0) != 0 ||
196 filler(buf, "..", NULL, 0) != 0 ||
197 filler(buf, "system", NULL, 0) != 0)
198 return -ENOENT;
199
200 return 0;
201 }
202 if (strcmp(path, "/sys/devices/system") == 0) {
203 if (filler(buf, ".", NULL, 0) != 0 ||
204 filler(buf, "..", NULL, 0) != 0 ||
205 filler(buf, "cpu", NULL, 0) != 0)
206 return -ENOENT;
207
208 return 0;
209 }
210 if (strcmp(path, "/sys/devices/system/cpu") == 0) {
211 if (filler(buf, ".", NULL, 0) != 0 ||
212 filler(buf, "..", NULL, 0) != 0 ||
213 filler(buf, "online", NULL, 0) != 0)
214 return -ENOENT;
215
216 return 0;
217 }
218
219 return 0;
220 }
221
222 __lxcfs_fuse_ops int sys_open(const char *path, struct fuse_file_info *fi)
223 {
224 __do_free struct file_info *info = NULL;
225 int type = -1;
226
227 if (strcmp(path, "/sys/devices") == 0)
228 type = LXC_TYPE_SYS_DEVICES;
229 if (strcmp(path, "/sys/devices/system") == 0)
230 type = LXC_TYPE_SYS_DEVICES_SYSTEM;
231 if (strcmp(path, "/sys/devices/system/cpu") == 0)
232 type = LXC_TYPE_SYS_DEVICES_SYSTEM_CPU;
233 if (strcmp(path, "/sys/devices/system/cpu/online") == 0)
234 type = LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE;
235 if (type == -1)
236 return -ENOENT;
237
238 info = malloc(sizeof(*info));
239 if (!info)
240 return -ENOMEM;
241
242 memset(info, 0, sizeof(*info));
243 info->type = type;
244
245 info->buflen = get_sysfile_size(path) + BUF_RESERVE_SIZE;
246
247 info->buf = malloc(info->buflen);
248 if (!info->buf)
249 return -ENOMEM;
250
251 memset(info->buf, 0, info->buflen);
252 /* set actual size to buffer size */
253 info->size = info->buflen;
254
255 fi->fh = PTR_TO_UINT64(move_ptr(info));
256 return 0;
257 }
258
259 __lxcfs_fuse_ops int sys_access(const char *path, int mask)
260 {
261 if (strcmp(path, "/sys") == 0 && access(path, R_OK) == 0)
262 return 0;
263
264 if (strcmp(path, "/sys/devices") == 0 && access(path, R_OK) == 0)
265 return 0;
266
267 if (strcmp(path, "/sys/devices/system") == 0 && access(path, R_OK) == 0)
268 return 0;
269
270 if (strcmp(path, "/sys/devices/system/cpu") == 0 &&
271 access(path, R_OK) == 0)
272 return 0;
273
274 /* these are all read-only */
275 if ((mask & ~R_OK) != 0)
276 return -EACCES;
277
278 return 0;
279 }
280
281 __lxcfs_fuse_ops int sys_release(const char *path, struct fuse_file_info *fi)
282 {
283 do_release_file_info(fi);
284 return 0;
285 }
286
287 __lxcfs_fuse_ops int sys_releasedir(const char *path, struct fuse_file_info *fi)
288 {
289 do_release_file_info(fi);
290 return 0;
291 }
292
293 __lxcfs_fuse_ops int sys_read(const char *path, char *buf, size_t size,
294 off_t offset, struct fuse_file_info *fi)
295 {
296 struct file_info *f = INTTYPE_TO_PTR(fi->fh);
297
298 switch (f->type) {
299 case LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE:
300 if (liblxcfs_functional())
301 return sys_devices_system_cpu_online_read(buf, size, offset, fi);
302
303 return read_file_fuse_with_offset(LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE_PATH,
304 buf, size, offset, f);
305 case LXC_TYPE_SYS_DEVICES:
306 break;
307 case LXC_TYPE_SYS_DEVICES_SYSTEM:
308 break;
309 case LXC_TYPE_SYS_DEVICES_SYSTEM_CPU:
310 break;
311 }
312
313 return -EINVAL;
314 }