mountfd 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +225 -0
- data/Rakefile +69 -0
- data/benchmark/mounts.rb +34 -0
- data/docs/kernel-notes.md +48 -0
- data/examples/atomic_swap.rb +12 -0
- data/examples/idmapped_volume.rb +17 -0
- data/examples/mini_container.rb +40 -0
- data/examples/readonly_sandbox.rb +39 -0
- data/ext/mountfd/compat.h +197 -0
- data/ext/mountfd/constants.c +53 -0
- data/ext/mountfd/extconf.rb +12 -0
- data/ext/mountfd/mount_info.c +166 -0
- data/ext/mountfd/mountfd.c +393 -0
- data/ext/mountfd/mountfd.h +17 -0
- data/ext/mountfd/namespace.c +74 -0
- data/ext/mountfd/user_namespace.c +220 -0
- data/lib/mountfd/attributes.rb +65 -0
- data/lib/mountfd/core.rb +346 -0
- data/lib/mountfd/mount_info.rb +78 -0
- data/lib/mountfd/namespace.rb +39 -0
- data/lib/mountfd/user_namespace.rb +84 -0
- data/lib/mountfd/version.rb +5 -0
- data/lib/mountfd.rb +32 -0
- data/sig/mountfd.rbs +119 -0
- data/tools/dump_constants.c +54 -0
- data/tools/generate_constants.rb +32 -0
- data/tools/research_idmap.rb +37 -0
- data/tools/vm/Makefile +8 -0
- data/tools/vm/config-fragment +7 -0
- data/tools/vm/run.sh +18 -0
- metadata +118 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
#ifndef MOUNTFD_COMPAT_H
|
|
2
|
+
#define MOUNTFD_COMPAT_H
|
|
3
|
+
|
|
4
|
+
#ifdef __linux__
|
|
5
|
+
# include <fcntl.h>
|
|
6
|
+
# include <stdint.h>
|
|
7
|
+
# include <sys/ioctl.h>
|
|
8
|
+
# include <sys/syscall.h>
|
|
9
|
+
# ifdef HAVE_LINUX_MOUNT_H
|
|
10
|
+
# include <linux/mount.h>
|
|
11
|
+
# endif
|
|
12
|
+
|
|
13
|
+
# ifndef SYS_open_tree
|
|
14
|
+
# define SYS_open_tree 428
|
|
15
|
+
# endif
|
|
16
|
+
# ifndef SYS_move_mount
|
|
17
|
+
# define SYS_move_mount 429
|
|
18
|
+
# endif
|
|
19
|
+
# ifndef SYS_fsopen
|
|
20
|
+
# define SYS_fsopen 430
|
|
21
|
+
# endif
|
|
22
|
+
# ifndef SYS_fsconfig
|
|
23
|
+
# define SYS_fsconfig 431
|
|
24
|
+
# endif
|
|
25
|
+
# ifndef SYS_fsmount
|
|
26
|
+
# define SYS_fsmount 432
|
|
27
|
+
# endif
|
|
28
|
+
# ifndef SYS_fspick
|
|
29
|
+
# define SYS_fspick 433
|
|
30
|
+
# endif
|
|
31
|
+
# ifndef SYS_mount_setattr
|
|
32
|
+
# define SYS_mount_setattr 442
|
|
33
|
+
# endif
|
|
34
|
+
# ifndef SYS_statmount
|
|
35
|
+
# define SYS_statmount 457
|
|
36
|
+
# endif
|
|
37
|
+
# ifndef SYS_listmount
|
|
38
|
+
# define SYS_listmount 458
|
|
39
|
+
# endif
|
|
40
|
+
# ifndef SYS_pivot_root
|
|
41
|
+
# ifdef __NR_pivot_root
|
|
42
|
+
# define SYS_pivot_root __NR_pivot_root
|
|
43
|
+
# elif defined(__x86_64__)
|
|
44
|
+
# define SYS_pivot_root 155
|
|
45
|
+
# elif defined(__aarch64__)
|
|
46
|
+
# define SYS_pivot_root 41
|
|
47
|
+
# else
|
|
48
|
+
# error "SYS_pivot_root is unavailable for this architecture"
|
|
49
|
+
# endif
|
|
50
|
+
# endif
|
|
51
|
+
|
|
52
|
+
# ifndef FSOPEN_CLOEXEC
|
|
53
|
+
# define FSOPEN_CLOEXEC 0x00000001
|
|
54
|
+
# endif
|
|
55
|
+
# ifndef FSPICK_CLOEXEC
|
|
56
|
+
# define FSPICK_CLOEXEC 0x00000001
|
|
57
|
+
# define FSPICK_SYMLINK_NOFOLLOW 0x00000002
|
|
58
|
+
# define FSPICK_NO_AUTOMOUNT 0x00000004
|
|
59
|
+
# define FSPICK_EMPTY_PATH 0x00000008
|
|
60
|
+
# endif
|
|
61
|
+
# ifndef FSCONFIG_SET_FLAG
|
|
62
|
+
# define FSCONFIG_SET_FLAG 0
|
|
63
|
+
# define FSCONFIG_SET_STRING 1
|
|
64
|
+
# define FSCONFIG_SET_BINARY 2
|
|
65
|
+
# define FSCONFIG_SET_PATH 3
|
|
66
|
+
# define FSCONFIG_SET_PATH_EMPTY 4
|
|
67
|
+
# define FSCONFIG_SET_FD 5
|
|
68
|
+
# define FSCONFIG_CMD_CREATE 6
|
|
69
|
+
# define FSCONFIG_CMD_RECONFIGURE 7
|
|
70
|
+
# endif
|
|
71
|
+
# ifndef FSCONFIG_CMD_CREATE_EXCL
|
|
72
|
+
# define FSCONFIG_CMD_CREATE_EXCL 8
|
|
73
|
+
# endif
|
|
74
|
+
# ifndef FSMOUNT_CLOEXEC
|
|
75
|
+
# define FSMOUNT_CLOEXEC 0x00000001
|
|
76
|
+
# endif
|
|
77
|
+
# ifndef OPEN_TREE_CLONE
|
|
78
|
+
# define OPEN_TREE_CLONE 1
|
|
79
|
+
# endif
|
|
80
|
+
# ifndef OPEN_TREE_CLOEXEC
|
|
81
|
+
# define OPEN_TREE_CLOEXEC O_CLOEXEC
|
|
82
|
+
# endif
|
|
83
|
+
# ifndef MOVE_MOUNT_F_SYMLINKS
|
|
84
|
+
# define MOVE_MOUNT_F_SYMLINKS 0x00000001
|
|
85
|
+
# define MOVE_MOUNT_F_AUTOMOUNTS 0x00000002
|
|
86
|
+
# define MOVE_MOUNT_F_EMPTY_PATH 0x00000004
|
|
87
|
+
# define MOVE_MOUNT_T_SYMLINKS 0x00000010
|
|
88
|
+
# define MOVE_MOUNT_T_AUTOMOUNTS 0x00000020
|
|
89
|
+
# define MOVE_MOUNT_T_EMPTY_PATH 0x00000040
|
|
90
|
+
# endif
|
|
91
|
+
# ifndef MOVE_MOUNT_SET_GROUP
|
|
92
|
+
# define MOVE_MOUNT_SET_GROUP 0x00000100
|
|
93
|
+
# endif
|
|
94
|
+
# ifndef MOVE_MOUNT_BENEATH
|
|
95
|
+
# define MOVE_MOUNT_BENEATH 0x00000200
|
|
96
|
+
# endif
|
|
97
|
+
# ifndef MOUNT_ATTR_RDONLY
|
|
98
|
+
# define MOUNT_ATTR_RDONLY 0x00000001ULL
|
|
99
|
+
# define MOUNT_ATTR_NOSUID 0x00000002ULL
|
|
100
|
+
# define MOUNT_ATTR_NODEV 0x00000004ULL
|
|
101
|
+
# define MOUNT_ATTR_NOEXEC 0x00000008ULL
|
|
102
|
+
# define MOUNT_ATTR__ATIME 0x00000070ULL
|
|
103
|
+
# define MOUNT_ATTR_RELATIME 0x00000000ULL
|
|
104
|
+
# define MOUNT_ATTR_NOATIME 0x00000010ULL
|
|
105
|
+
# define MOUNT_ATTR_STRICTATIME 0x00000020ULL
|
|
106
|
+
# define MOUNT_ATTR_NODIRATIME 0x00000080ULL
|
|
107
|
+
# endif
|
|
108
|
+
# ifndef MOUNT_ATTR_IDMAP
|
|
109
|
+
# define MOUNT_ATTR_IDMAP 0x00100000ULL
|
|
110
|
+
# endif
|
|
111
|
+
# ifndef MOUNT_ATTR_NOSYMFOLLOW
|
|
112
|
+
# define MOUNT_ATTR_NOSYMFOLLOW 0x00200000ULL
|
|
113
|
+
# endif
|
|
114
|
+
# ifndef MOUNT_ATTR_SIZE_VER0
|
|
115
|
+
# define MOUNT_ATTR_SIZE_VER0 32
|
|
116
|
+
struct mount_attr {
|
|
117
|
+
uint64_t attr_set;
|
|
118
|
+
uint64_t attr_clr;
|
|
119
|
+
uint64_t propagation;
|
|
120
|
+
uint64_t userns_fd;
|
|
121
|
+
};
|
|
122
|
+
# endif
|
|
123
|
+
# ifndef AT_RECURSIVE
|
|
124
|
+
# define AT_RECURSIVE 0x8000
|
|
125
|
+
# endif
|
|
126
|
+
# ifndef AT_EMPTY_PATH
|
|
127
|
+
# define AT_EMPTY_PATH 0x1000
|
|
128
|
+
# endif
|
|
129
|
+
# ifndef MS_UNBINDABLE
|
|
130
|
+
# define MS_UNBINDABLE (1 << 17)
|
|
131
|
+
# endif
|
|
132
|
+
# ifndef MS_REC
|
|
133
|
+
# define MS_REC 16384
|
|
134
|
+
# endif
|
|
135
|
+
# ifndef MS_PRIVATE
|
|
136
|
+
# define MS_PRIVATE (1 << 18)
|
|
137
|
+
# endif
|
|
138
|
+
# ifndef MS_SLAVE
|
|
139
|
+
# define MS_SLAVE (1 << 19)
|
|
140
|
+
# endif
|
|
141
|
+
# ifndef MS_SHARED
|
|
142
|
+
# define MS_SHARED (1 << 20)
|
|
143
|
+
# endif
|
|
144
|
+
# ifndef CLONE_NEWNS
|
|
145
|
+
# define CLONE_NEWNS 0x00020000
|
|
146
|
+
# endif
|
|
147
|
+
# ifndef CLONE_NEWUSER
|
|
148
|
+
# define CLONE_NEWUSER 0x10000000
|
|
149
|
+
# endif
|
|
150
|
+
# ifndef NSIO
|
|
151
|
+
# define NSIO 0xb7
|
|
152
|
+
# endif
|
|
153
|
+
# ifndef NS_GET_MNTNS_ID
|
|
154
|
+
# define NS_GET_MNTNS_ID _IOR(NSIO, 0x5, uint64_t)
|
|
155
|
+
# endif
|
|
156
|
+
# ifndef MNT_ID_REQ_SIZE_VER0
|
|
157
|
+
# define MNT_ID_REQ_SIZE_VER0 24
|
|
158
|
+
# endif
|
|
159
|
+
# ifndef MNT_ID_REQ_SIZE_VER1
|
|
160
|
+
# define MNT_ID_REQ_SIZE_VER1 32
|
|
161
|
+
# endif
|
|
162
|
+
# ifndef STATMOUNT_SB_BASIC
|
|
163
|
+
# define STATMOUNT_SB_BASIC 0x00000001U
|
|
164
|
+
# endif
|
|
165
|
+
# ifndef STATMOUNT_MNT_BASIC
|
|
166
|
+
# define STATMOUNT_MNT_BASIC 0x00000002U
|
|
167
|
+
# endif
|
|
168
|
+
# ifndef STATMOUNT_PROPAGATE_FROM
|
|
169
|
+
# define STATMOUNT_PROPAGATE_FROM 0x00000004U
|
|
170
|
+
# endif
|
|
171
|
+
# ifndef STATMOUNT_MNT_ROOT
|
|
172
|
+
# define STATMOUNT_MNT_ROOT 0x00000008U
|
|
173
|
+
# endif
|
|
174
|
+
# ifndef STATMOUNT_MNT_POINT
|
|
175
|
+
# define STATMOUNT_MNT_POINT 0x00000010U
|
|
176
|
+
# endif
|
|
177
|
+
# ifndef STATMOUNT_FS_TYPE
|
|
178
|
+
# define STATMOUNT_FS_TYPE 0x00000020U
|
|
179
|
+
# endif
|
|
180
|
+
# ifndef STATMOUNT_MNT_NS_ID
|
|
181
|
+
# define STATMOUNT_MNT_NS_ID 0x00000040U
|
|
182
|
+
# endif
|
|
183
|
+
# ifndef STATMOUNT_MNT_OPTS
|
|
184
|
+
# define STATMOUNT_MNT_OPTS 0x00000080U
|
|
185
|
+
# endif
|
|
186
|
+
# ifndef STATMOUNT_FS_SUBTYPE
|
|
187
|
+
# define STATMOUNT_FS_SUBTYPE 0x00000100U
|
|
188
|
+
# endif
|
|
189
|
+
# ifndef STATMOUNT_SB_SOURCE
|
|
190
|
+
# define STATMOUNT_SB_SOURCE 0x00000200U
|
|
191
|
+
# endif
|
|
192
|
+
# ifndef LSMT_ROOT
|
|
193
|
+
# define LSMT_ROOT UINT64_MAX
|
|
194
|
+
# endif
|
|
195
|
+
#endif
|
|
196
|
+
|
|
197
|
+
#endif
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/* Generated by tools/generate_constants.rb from Linux UAPI headers. */
|
|
2
|
+
#include "ruby.h"
|
|
3
|
+
|
|
4
|
+
void mountfd_define_constants(VALUE native)
|
|
5
|
+
{
|
|
6
|
+
#define DEF(name, value) rb_define_const(native, name, ULL2NUM(value))
|
|
7
|
+
DEF("FSOPEN_CLOEXEC", 1ULL);
|
|
8
|
+
DEF("FSPICK_CLOEXEC", 1ULL);
|
|
9
|
+
DEF("FSPICK_SYMLINK_NOFOLLOW", 2ULL);
|
|
10
|
+
DEF("FSPICK_NO_AUTOMOUNT", 4ULL);
|
|
11
|
+
DEF("FSPICK_EMPTY_PATH", 8ULL);
|
|
12
|
+
DEF("FSCONFIG_SET_FLAG", 0ULL);
|
|
13
|
+
DEF("FSCONFIG_SET_STRING", 1ULL);
|
|
14
|
+
DEF("FSCONFIG_SET_BINARY", 2ULL);
|
|
15
|
+
DEF("FSCONFIG_SET_PATH", 3ULL);
|
|
16
|
+
DEF("FSCONFIG_SET_PATH_EMPTY", 4ULL);
|
|
17
|
+
DEF("FSCONFIG_SET_FD", 5ULL);
|
|
18
|
+
DEF("FSCONFIG_CMD_CREATE", 6ULL);
|
|
19
|
+
DEF("FSCONFIG_CMD_RECONFIGURE", 7ULL);
|
|
20
|
+
DEF("FSCONFIG_CMD_CREATE_EXCL", 8ULL);
|
|
21
|
+
DEF("FSMOUNT_CLOEXEC", 1ULL);
|
|
22
|
+
DEF("OPEN_TREE_CLONE", 1ULL);
|
|
23
|
+
DEF("OPEN_TREE_CLOEXEC", 524288ULL);
|
|
24
|
+
DEF("MOVE_MOUNT_F_SYMLINKS", 1ULL);
|
|
25
|
+
DEF("MOVE_MOUNT_F_AUTOMOUNTS", 2ULL);
|
|
26
|
+
DEF("MOVE_MOUNT_F_EMPTY_PATH", 4ULL);
|
|
27
|
+
DEF("MOVE_MOUNT_T_SYMLINKS", 16ULL);
|
|
28
|
+
DEF("MOVE_MOUNT_T_AUTOMOUNTS", 32ULL);
|
|
29
|
+
DEF("MOVE_MOUNT_T_EMPTY_PATH", 64ULL);
|
|
30
|
+
DEF("MOVE_MOUNT_SET_GROUP", 256ULL);
|
|
31
|
+
DEF("MOVE_MOUNT_BENEATH", 512ULL);
|
|
32
|
+
DEF("MOUNT_ATTR_RDONLY", 1ULL);
|
|
33
|
+
DEF("MOUNT_ATTR_NOSUID", 2ULL);
|
|
34
|
+
DEF("MOUNT_ATTR_NODEV", 4ULL);
|
|
35
|
+
DEF("MOUNT_ATTR_NOEXEC", 8ULL);
|
|
36
|
+
DEF("MOUNT_ATTR__ATIME", 112ULL);
|
|
37
|
+
DEF("MOUNT_ATTR_RELATIME", 0ULL);
|
|
38
|
+
DEF("MOUNT_ATTR_NOATIME", 16ULL);
|
|
39
|
+
DEF("MOUNT_ATTR_STRICTATIME", 32ULL);
|
|
40
|
+
DEF("MOUNT_ATTR_NODIRATIME", 128ULL);
|
|
41
|
+
DEF("MOUNT_ATTR_IDMAP", 1048576ULL);
|
|
42
|
+
DEF("MOUNT_ATTR_NOSYMFOLLOW", 2097152ULL);
|
|
43
|
+
DEF("AT_RECURSIVE", 32768ULL);
|
|
44
|
+
DEF("AT_EMPTY_PATH", 4096ULL);
|
|
45
|
+
DEF("MS_UNBINDABLE", 131072ULL);
|
|
46
|
+
DEF("MS_REC", 16384ULL);
|
|
47
|
+
DEF("MS_PRIVATE", 262144ULL);
|
|
48
|
+
DEF("MS_SLAVE", 524288ULL);
|
|
49
|
+
DEF("MS_SHARED", 1048576ULL);
|
|
50
|
+
DEF("CLONE_NEWNS", 131072ULL);
|
|
51
|
+
DEF("CLONE_NEWUSER", 268435456ULL);
|
|
52
|
+
#undef DEF
|
|
53
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "mkmf"
|
|
4
|
+
|
|
5
|
+
have_header("linux/mount.h")
|
|
6
|
+
have_header("sys/mount.h")
|
|
7
|
+
have_header("sys/syscall.h")
|
|
8
|
+
have_header("sched.h")
|
|
9
|
+
have_func("syscall", "unistd.h")
|
|
10
|
+
have_func("unshare", "sched.h")
|
|
11
|
+
create_header
|
|
12
|
+
create_makefile("mountfd/mountfd")
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#include "ruby.h"
|
|
2
|
+
#include "mountfd.h"
|
|
3
|
+
#include "compat.h"
|
|
4
|
+
|
|
5
|
+
#ifdef __linux__
|
|
6
|
+
#include <errno.h>
|
|
7
|
+
#include <stdint.h>
|
|
8
|
+
#include <stdlib.h>
|
|
9
|
+
#include <string.h>
|
|
10
|
+
#include <sys/ioctl.h>
|
|
11
|
+
#include <unistd.h>
|
|
12
|
+
|
|
13
|
+
#define MOUNTFD_STAT_SIZE 512
|
|
14
|
+
#define MOUNTFD_STAT_MASK (STATMOUNT_SB_BASIC | STATMOUNT_MNT_BASIC | \
|
|
15
|
+
STATMOUNT_PROPAGATE_FROM | STATMOUNT_MNT_ROOT | STATMOUNT_MNT_POINT | \
|
|
16
|
+
STATMOUNT_FS_TYPE | STATMOUNT_MNT_NS_ID | STATMOUNT_MNT_OPTS | \
|
|
17
|
+
STATMOUNT_FS_SUBTYPE | STATMOUNT_SB_SOURCE)
|
|
18
|
+
|
|
19
|
+
struct mountfd_mnt_id_req {
|
|
20
|
+
uint32_t size;
|
|
21
|
+
uint32_t spare;
|
|
22
|
+
uint64_t mnt_id;
|
|
23
|
+
uint64_t param;
|
|
24
|
+
uint64_t mnt_ns_id;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
struct mountfd_statmount {
|
|
28
|
+
uint32_t size;
|
|
29
|
+
uint32_t mnt_opts;
|
|
30
|
+
uint64_t mask;
|
|
31
|
+
uint32_t dev_major;
|
|
32
|
+
uint32_t dev_minor;
|
|
33
|
+
uint64_t sb_magic;
|
|
34
|
+
uint32_t sb_flags;
|
|
35
|
+
uint32_t fs_type;
|
|
36
|
+
uint64_t mnt_id;
|
|
37
|
+
uint64_t parent_id;
|
|
38
|
+
uint32_t old_id;
|
|
39
|
+
uint32_t old_parent_id;
|
|
40
|
+
uint64_t attrs;
|
|
41
|
+
uint64_t propagation;
|
|
42
|
+
uint64_t peer_group;
|
|
43
|
+
uint64_t master;
|
|
44
|
+
uint64_t propagate_from;
|
|
45
|
+
uint32_t root;
|
|
46
|
+
uint32_t point;
|
|
47
|
+
uint64_t namespace_id;
|
|
48
|
+
uint32_t fs_subtype;
|
|
49
|
+
uint32_t source;
|
|
50
|
+
unsigned char reserved[MOUNTFD_STAT_SIZE - 128];
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
static VALUE symbol(const char *name)
|
|
54
|
+
{
|
|
55
|
+
return ID2SYM(rb_intern(name));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
static VALUE stat_string(char *buffer, size_t capacity, uint32_t offset)
|
|
59
|
+
{
|
|
60
|
+
struct mountfd_statmount *stat = (struct mountfd_statmount *)buffer;
|
|
61
|
+
size_t position = MOUNTFD_STAT_SIZE + offset;
|
|
62
|
+
size_t available;
|
|
63
|
+
if (position >= capacity || position >= stat->size) return Qnil;
|
|
64
|
+
available = stat->size < capacity ? stat->size - position : capacity - position;
|
|
65
|
+
return rb_str_new(buffer + position, strnlen(buffer + position, available));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static VALUE stat_hash(char *buffer, size_t capacity)
|
|
69
|
+
{
|
|
70
|
+
struct mountfd_statmount *stat = (struct mountfd_statmount *)buffer;
|
|
71
|
+
VALUE hash = rb_hash_new();
|
|
72
|
+
#define PUT(name, value) rb_hash_aset(hash, symbol(name), value)
|
|
73
|
+
PUT("mnt_id", ULL2NUM(stat->mnt_id));
|
|
74
|
+
PUT("parent_id", ULL2NUM(stat->parent_id));
|
|
75
|
+
PUT("old_id", UINT2NUM(stat->old_id));
|
|
76
|
+
PUT("old_parent_id", UINT2NUM(stat->old_parent_id));
|
|
77
|
+
PUT("dev_major", UINT2NUM(stat->dev_major));
|
|
78
|
+
PUT("dev_minor", UINT2NUM(stat->dev_minor));
|
|
79
|
+
PUT("attrs", ULL2NUM(stat->attrs));
|
|
80
|
+
PUT("propagation", ULL2NUM(stat->propagation));
|
|
81
|
+
PUT("peer_group", ULL2NUM(stat->peer_group));
|
|
82
|
+
PUT("master", ULL2NUM(stat->master));
|
|
83
|
+
PUT("propagate_from", ULL2NUM(stat->propagate_from));
|
|
84
|
+
PUT("mnt_root", (stat->mask & STATMOUNT_MNT_ROOT) ? stat_string(buffer, capacity, stat->root) : Qnil);
|
|
85
|
+
PUT("mount_point", (stat->mask & STATMOUNT_MNT_POINT) ? stat_string(buffer, capacity, stat->point) : Qnil);
|
|
86
|
+
PUT("fs_type", (stat->mask & STATMOUNT_FS_TYPE) ? stat_string(buffer, capacity, stat->fs_type) : Qnil);
|
|
87
|
+
PUT("source", (stat->mask & STATMOUNT_SB_SOURCE) ? stat_string(buffer, capacity, stat->source) : Qnil);
|
|
88
|
+
PUT("options", (stat->mask & STATMOUNT_MNT_OPTS) ? stat_string(buffer, capacity, stat->mnt_opts) : Qnil);
|
|
89
|
+
#undef PUT
|
|
90
|
+
return hash;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
static VALUE stat_one(uint64_t id, uint64_t namespace_id, int namespace_selected)
|
|
94
|
+
{
|
|
95
|
+
struct mountfd_mnt_id_req request = {
|
|
96
|
+
namespace_selected ? MNT_ID_REQ_SIZE_VER1 : MNT_ID_REQ_SIZE_VER0,
|
|
97
|
+
0, id, MOUNTFD_STAT_MASK, namespace_id
|
|
98
|
+
};
|
|
99
|
+
size_t capacity = 4096;
|
|
100
|
+
char *buffer = NULL;
|
|
101
|
+
long result;
|
|
102
|
+
|
|
103
|
+
while (capacity <= 1024 * 1024) {
|
|
104
|
+
buffer = realloc(buffer, capacity);
|
|
105
|
+
if (!buffer) rb_memerror();
|
|
106
|
+
memset(buffer, 0, capacity);
|
|
107
|
+
result = syscall(SYS_statmount, &request, buffer, capacity, 0);
|
|
108
|
+
if (result == 0) {
|
|
109
|
+
VALUE hash = stat_hash(buffer, capacity);
|
|
110
|
+
free(buffer);
|
|
111
|
+
return hash;
|
|
112
|
+
}
|
|
113
|
+
if (errno == ENOENT) { free(buffer); return Qnil; }
|
|
114
|
+
if (errno != EOVERFLOW) {
|
|
115
|
+
int error = errno;
|
|
116
|
+
free(buffer); errno = error; mountfd_syscall_failed("statmount");
|
|
117
|
+
}
|
|
118
|
+
capacity *= 2;
|
|
119
|
+
}
|
|
120
|
+
free(buffer);
|
|
121
|
+
rb_raise(rb_eRuntimeError, "statmount response exceeds 1 MiB");
|
|
122
|
+
}
|
|
123
|
+
#endif
|
|
124
|
+
|
|
125
|
+
static VALUE native_statmounts(VALUE self, VALUE namespace_fd)
|
|
126
|
+
{
|
|
127
|
+
#ifdef __linux__
|
|
128
|
+
uint64_t namespace_id = 0;
|
|
129
|
+
int namespace_selected = !NIL_P(namespace_fd);
|
|
130
|
+
struct mountfd_mnt_id_req request = {MNT_ID_REQ_SIZE_VER0, 0, LSMT_ROOT, 0, 0};
|
|
131
|
+
uint64_t ids[256];
|
|
132
|
+
VALUE mounts = rb_ary_new();
|
|
133
|
+
long count;
|
|
134
|
+
size_t index;
|
|
135
|
+
|
|
136
|
+
if (namespace_selected) {
|
|
137
|
+
if (ioctl(NUM2INT(namespace_fd), NS_GET_MNTNS_ID, &namespace_id) < 0)
|
|
138
|
+
mountfd_syscall_failed("NS_GET_MNTNS_ID");
|
|
139
|
+
request.size = MNT_ID_REQ_SIZE_VER1;
|
|
140
|
+
request.mnt_ns_id = namespace_id;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
while (1) {
|
|
144
|
+
count = syscall(SYS_listmount, &request, ids, 256, 0);
|
|
145
|
+
if (count < 0) mountfd_syscall_failed("listmount");
|
|
146
|
+
if (count == 0) break;
|
|
147
|
+
for (index = 0; index < (size_t)count; index++) {
|
|
148
|
+
VALUE value = stat_one(ids[index], namespace_id, namespace_selected);
|
|
149
|
+
if (!NIL_P(value)) rb_ary_push(mounts, value);
|
|
150
|
+
}
|
|
151
|
+
request.param = ids[count - 1];
|
|
152
|
+
if (count < 256) break;
|
|
153
|
+
}
|
|
154
|
+
return mounts;
|
|
155
|
+
#else
|
|
156
|
+
(void)namespace_fd;
|
|
157
|
+
VALUE mountfd = rb_const_get(rb_cObject, rb_intern("Mountfd"));
|
|
158
|
+
VALUE error = rb_const_get(mountfd, rb_intern("UnsupportedError"));
|
|
159
|
+
rb_raise(error, "statmount is unavailable on this platform");
|
|
160
|
+
#endif
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
void mountfd_mount_info_init(VALUE native)
|
|
164
|
+
{
|
|
165
|
+
rb_define_singleton_method(native, "statmounts", native_statmounts, 1);
|
|
166
|
+
}
|