]> git.proxmox.com Git - mirror_lxcfs.git/blame - src/sysfs_fuse.c
proc_fuse: coding style
[mirror_lxcfs.git] / src / sysfs_fuse.c
CommitLineData
71f17cd2
YB
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
1f5596dd
CB
3#ifndef _GNU_SOURCE
4#define _GNU_SOURCE
5#endif
6
7#ifndef FUSE_USE_VERSION
71f17cd2 8#define FUSE_USE_VERSION 26
1f5596dd
CB
9#endif
10
11#define _FILE_OFFSET_BITS 64
71f17cd2
YB
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"
700dd417 42#include "memory_utils.h"
77f4399a
CB
43#include "cgroups/cgroup.h"
44#include "config.h"
71f17cd2 45#include "sysfs_fuse.h"
1d81c6a6 46#include "utils.h"
71f17cd2 47
71f17cd2
YB
48static int sys_devices_system_cpu_online_read(char *buf, size_t size,
49 off_t offset,
50 struct fuse_file_info *fi)
51{
700dd417 52 __do_free char *cg = NULL, *cpuset = NULL;
71f17cd2 53 struct fuse_context *fc = fuse_get_context();
99b183fb 54 struct file_info *d = INTTYPE_TO_PTR(fi->fh);
71f17cd2 55 char *cache = d->buf;
71f17cd2
YB
56 bool use_view;
57
58 int max_cpus = 0;
59 pid_t initpid;
60 ssize_t total_len = 0;
61
62 if (offset) {
700dd417
CB
63 int left;
64
71f17cd2
YB
65 if (!d->cached)
66 return 0;
700dd417 67
71f17cd2
YB
68 if (offset > d->size)
69 return -EINVAL;
700dd417
CB
70
71 left = d->size - offset;
71f17cd2
YB
72 total_len = left > size ? size : left;
73 memcpy(buf, cache + offset, total_len);
700dd417 74
71f17cd2
YB
75 return total_len;
76 }
77
78 initpid = lookup_initpid_in_store(fc->pid);
79 if (initpid <= 0)
80 initpid = fc->pid;
81 cg = get_pid_cgroup(initpid, "cpuset");
82 if (!cg)
5fbea8a6 83 return read_file_fuse("/sys/devices/system/cpu/online", buf, size, d);
71f17cd2
YB
84 prune_init_slice(cg);
85
86 cpuset = get_cpuset(cg);
87 if (!cpuset)
700dd417 88 return 0;
71f17cd2 89
77f4399a 90 use_view = cgroup_ops->can_use_cpuview(cgroup_ops);
71f17cd2
YB
91 if (use_view)
92 max_cpus = max_cpu_count(cg);
93
94 if (max_cpus == 0)
5fbea8a6 95 return read_file_fuse("/sys/devices/system/cpu/online", buf, size, d);
71f17cd2
YB
96 if (max_cpus > 1)
97 total_len = snprintf(d->buf, d->buflen, "0-%d\n", max_cpus - 1);
98 else
99 total_len = snprintf(d->buf, d->buflen, "0\n");
100 if (total_len < 0 || total_len >= d->buflen) {
101 lxcfs_error("%s\n", "failed to write to cache");
102 return 0;
103 }
104
105 d->size = (int)total_len;
106 d->cached = 1;
107
108 if (total_len > size)
109 total_len = size;
110
111 memcpy(buf, d->buf, total_len);
700dd417 112
71f17cd2
YB
113 return total_len;
114}
115
116static off_t get_sysfile_size(const char *which)
117{
700dd417
CB
118 __do_fclose FILE *f = NULL;
119 __do_free char *line = NULL;
71f17cd2
YB
120 size_t len = 0;
121 ssize_t sz, answer = 0;
122
700dd417 123 f = fopen(which, "re");
71f17cd2
YB
124 if (!f)
125 return 0;
126
127 while ((sz = getline(&line, &len, f)) != -1)
128 answer += sz;
71f17cd2
YB
129
130 return answer;
131}
132
133int sys_getattr(const char *path, struct stat *sb)
134{
135 struct timespec now;
136
137 memset(sb, 0, sizeof(struct stat));
138 if (clock_gettime(CLOCK_REALTIME, &now) < 0)
139 return -EINVAL;
140 sb->st_uid = sb->st_gid = 0;
141 sb->st_atim = sb->st_mtim = sb->st_ctim = now;
142 if (strcmp(path, "/sys") == 0) {
143 sb->st_mode = S_IFDIR | 00555;
144 sb->st_nlink = 2;
145 return 0;
146 }
147 if (strcmp(path, "/sys/devices") == 0) {
148 sb->st_mode = S_IFDIR | 00555;
149 sb->st_nlink = 2;
150 return 0;
151 }
152 if (strcmp(path, "/sys/devices/system") == 0) {
153 sb->st_mode = S_IFDIR | 00555;
154 sb->st_nlink = 2;
155 return 0;
156 }
157 if (strcmp(path, "/sys/devices/system/cpu") == 0) {
158 sb->st_mode = S_IFDIR | 00555;
159 sb->st_nlink = 2;
160 return 0;
161 }
162 if (strcmp(path, "/sys/devices/system/cpu/online") == 0) {
163 sb->st_size = 0;
164 sb->st_mode = S_IFREG | 00444;
165 sb->st_nlink = 1;
166 return 0;
167 }
168
169 return -ENOENT;
170}
171
172int sys_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
173 off_t offset, struct fuse_file_info *fi)
174{
175 if (strcmp(path, "/sys") == 0) {
176 if (filler(buf, ".", NULL, 0) != 0 ||
177 filler(buf, "..", NULL, 0) != 0 ||
178 filler(buf, "devices", NULL, 0) != 0)
179 return -ENOENT;
180 return 0;
181 }
182 if (strcmp(path, "/sys/devices") == 0) {
183 if (filler(buf, ".", NULL, 0) != 0 ||
184 filler(buf, "..", NULL, 0) != 0 ||
185 filler(buf, "system", NULL, 0) != 0)
186 return -ENOENT;
187 return 0;
188 }
189 if (strcmp(path, "/sys/devices/system") == 0) {
190 if (filler(buf, ".", NULL, 0) != 0 ||
191 filler(buf, "..", NULL, 0) != 0 ||
192 filler(buf, "cpu", NULL, 0) != 0)
193 return -ENOENT;
194 return 0;
195 }
196 if (strcmp(path, "/sys/devices/system/cpu") == 0) {
197 if (filler(buf, ".", NULL, 0) != 0 ||
198 filler(buf, "..", NULL, 0) != 0 ||
199 filler(buf, "online", NULL, 0) != 0)
200 return -ENOENT;
201 return 0;
202 }
203
204 return 0;
205}
206
207int sys_open(const char *path, struct fuse_file_info *fi)
208{
700dd417 209 __do_free struct file_info *info = NULL;
71f17cd2 210 int type = -1;
71f17cd2
YB
211
212 if (strcmp(path, "/sys/devices") == 0)
213 type = LXC_TYPE_SYS_DEVICES;
214 if (strcmp(path, "/sys/devices/system") == 0)
215 type = LXC_TYPE_SYS_DEVICES_SYSTEM;
216 if (strcmp(path, "/sys/devices/system/cpu") == 0)
217 type = LXC_TYPE_SYS_DEVICES_SYSTEM_CPU;
218 if (strcmp(path, "/sys/devices/system/cpu/online") == 0)
219 type = LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE;
220 if (type == -1)
221 return -ENOENT;
222
223 info = malloc(sizeof(*info));
224 if (!info)
225 return -ENOMEM;
226
227 memset(info, 0, sizeof(*info));
228 info->type = type;
229
230 info->buflen = get_sysfile_size(path) + BUF_RESERVE_SIZE;
700dd417
CB
231
232 info->buf = malloc(info->buflen);
233 if (!info->buf)
234 return -ENOMEM;
235
71f17cd2
YB
236 memset(info->buf, 0, info->buflen);
237 /* set actual size to buffer size */
238 info->size = info->buflen;
239
700dd417 240 fi->fh = PTR_TO_UINT64(move_ptr(info));
71f17cd2
YB
241 return 0;
242}
243
244int sys_access(const char *path, int mask)
245{
246 if (strcmp(path, "/sys") == 0 && access(path, R_OK) == 0)
247 return 0;
248 if (strcmp(path, "/sys/devices") == 0 && access(path, R_OK) == 0)
249 return 0;
250 if (strcmp(path, "/sys/devices/system") == 0 && access(path, R_OK) == 0)
251 return 0;
252 if (strcmp(path, "/sys/devices/system/cpu") == 0 &&
253 access(path, R_OK) == 0)
254 return 0;
255 /* these are all read-only */
256 if ((mask & ~R_OK) != 0)
257 return -EACCES;
258 return 0;
259}
260
261int sys_release(const char *path, struct fuse_file_info *fi)
262{
263 do_release_file_info(fi);
264 return 0;
265}
266
267int sys_releasedir(const char *path, struct fuse_file_info *fi)
268{
269 do_release_file_info(fi);
270 return 0;
271}
272
273int sys_read(const char *path, char *buf, size_t size, off_t offset,
274 struct fuse_file_info *fi)
275{
99b183fb 276 struct file_info *f = INTTYPE_TO_PTR(fi->fh);
71f17cd2
YB
277
278 switch (f->type) {
36817cdd
YB
279 case LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE:
280 return sys_devices_system_cpu_online_read(buf, size, offset, fi);
71f17cd2 281 case LXC_TYPE_SYS_DEVICES:
700dd417 282 break;
71f17cd2 283 case LXC_TYPE_SYS_DEVICES_SYSTEM:
700dd417 284 break;
71f17cd2 285 case LXC_TYPE_SYS_DEVICES_SYSTEM_CPU:
700dd417 286 break;
71f17cd2 287 }
700dd417
CB
288
289 return -EINVAL;
71f17cd2 290}