hrr_rb_lxns 0.2.1 → 0.3.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 +4 -4
- data/README.md +39 -1
- data/ext/hrr_rb_lxns/hrr_rb_lxns.c +9 -0
- data/lib/hrr_rb_lxns/files/file.rb +33 -0
- data/lib/hrr_rb_lxns/files.rb +130 -0
- data/lib/hrr_rb_lxns/version.rb +1 -1
- data/lib/hrr_rb_lxns.rb +176 -12
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2638d4c8b3db4d56a38f2eb038b9079f8449e20645a875a2a3c11c31099716a
|
4
|
+
data.tar.gz: 1b92b52c8db60ba8ebd6b5f517a74daf8125986fc52c1719c51416875ec015d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73a2767cf322ee5ba66f2187e81e5878a4233e11baa32c8a24ee87b1ecede422a52cada11f263af2bcd34c2a9d219e25be467b668fb8e6a7b37591b668bbe2de
|
7
|
+
data.tar.gz: c674dbbabb9c3708255dab0480acd8c8be21fe8c0635fc68c694441c2d14b7845b513b3a85074adb10123b941555a0dd3ca7ede5abf16302aa797e4cfccfaaf6
|
data/README.md
CHANGED
@@ -23,7 +23,7 @@ Or install it yourself as:
|
|
23
23
|
|
24
24
|
## Usage
|
25
25
|
|
26
|
-
hrr_rb_lxns provides unshare and setns wrappers.
|
26
|
+
hrr_rb_lxns provides unshare and setns wrappers, and namespace files information collector.
|
27
27
|
|
28
28
|
### Unshare
|
29
29
|
|
@@ -78,6 +78,28 @@ else
|
|
78
78
|
end
|
79
79
|
```
|
80
80
|
|
81
|
+
HrrRbLxns.unshare also supports mapping UIDs and/or GIDs for user namespace. When `:map_gid` option is specified, the method also writes `deny\n` in /proc/PID/setgroups.
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
options = {:map_uid => [[0, 0, 1], [1, 10000, 1000]]}
|
85
|
+
HrrRbLxns.unshare HrrRbLxns::NEWUSER, options # => 0
|
86
|
+
File.read("/proc/self/uid_map").gsub(/ +/, " ") # => " 0 0 1\n 1 10000 1000\n"
|
87
|
+
|
88
|
+
options = {:map_uid => "0 0 1", :map_gid => "0 0 1"}
|
89
|
+
HrrRbLxns.unshare HrrRbLxns::NEWUSER, options # => 0
|
90
|
+
File.read("/proc/self/uid_map").gsub(/ +/, " ") # => " 0 0 1\n"
|
91
|
+
File.read("/proc/self/setgroups") # => "deny\n"
|
92
|
+
File.read("/proc/self/gid_map").gsub(/ +/, " ") # => " 0 0 1\n"
|
93
|
+
```
|
94
|
+
|
95
|
+
Time namespace provides per-namespace monotonic and boottime clocks. The clock offsets can be set by `:monotonic` and `:boottime` options.
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
options = {:monotonic => 123.456, :boottime => "123.456"}
|
99
|
+
HrrRbLxns.unshare HrrRbLxns::NEWTIME, options # => 0
|
100
|
+
File.read("/proc/self/timens_offsets").gsub(/ +/, " ") # => "monotonic 123 456000000\nboottime 123 456000000\n"
|
101
|
+
```
|
102
|
+
|
81
103
|
### Setns
|
82
104
|
|
83
105
|
HrrRbLxns.setns method wraps around setns(2) system call. The system call associate the caller process's namespace to an existing one, which is disassociated by some other process.
|
@@ -110,6 +132,22 @@ system "ip netns add ns0"
|
|
110
132
|
HrrRbLxns.setns HrrRbLxns::NETNET, nil, {network: "/run/netns/ns0"}
|
111
133
|
```
|
112
134
|
|
135
|
+
### Files
|
136
|
+
|
137
|
+
HrrRbLxns.files Collects the caller process's or a specific process's namespace files information, which are the file path and its inode number.
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
# Collects the caller process's namespace files information
|
141
|
+
files = HrrRbLxns.files
|
142
|
+
# Collects a specific process's namespace files information
|
143
|
+
files = HrrRbLxns.files 12345
|
144
|
+
|
145
|
+
# Then, paths and their inode numbers are accesible
|
146
|
+
files.uts.path # => "/proc/12345/ns/uts"
|
147
|
+
files[:ipc].ino # => 4026531839
|
148
|
+
files["net"].ino # => 4026531840
|
149
|
+
```
|
150
|
+
|
113
151
|
## Note
|
114
152
|
|
115
153
|
Some of the namespace operations are not multi-thread friendly. The library expects that only main thread is running before unshare or setns operation.
|
@@ -2,6 +2,7 @@
|
|
2
2
|
#define _GNU_SOURCE 1
|
3
3
|
#include <sched.h>
|
4
4
|
#include <linux/version.h>
|
5
|
+
#include <time.h>
|
5
6
|
|
6
7
|
VALUE rb_mHrrRbLxns;
|
7
8
|
VALUE rb_mHrrRbLxnsConst;
|
@@ -117,4 +118,12 @@ Init_hrr_rb_lxns(void)
|
|
117
118
|
/* Represents time namespace. */
|
118
119
|
rb_define_const(rb_mHrrRbLxnsConst, "NEWTIME", INT2FIX(CLONE_NEWTIME));
|
119
120
|
#endif
|
121
|
+
#ifdef CLOCK_MONOTONIC
|
122
|
+
/* Represents monotonic clock. */
|
123
|
+
rb_define_const(rb_mHrrRbLxnsConst, "MONOTONIC", INT2FIX(CLOCK_MONOTONIC));
|
124
|
+
#endif
|
125
|
+
#ifdef CLOCK_BOOTTIME
|
126
|
+
/* Represents boottime clock. */
|
127
|
+
rb_define_const(rb_mHrrRbLxnsConst, "BOOTTIME", INT2FIX(CLOCK_BOOTTIME));
|
128
|
+
#endif
|
120
129
|
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module HrrRbLxns
|
2
|
+
class Files
|
3
|
+
|
4
|
+
# A class that takes a path to a namespace file and collects then keeps its inode.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# file = HrrRbLxns::Files::File.new "/proc/12345/ns/uts"
|
8
|
+
# file.path # => "/proc/12345/ns/uts"
|
9
|
+
# file.ino # => 4026531839
|
10
|
+
#
|
11
|
+
class File
|
12
|
+
|
13
|
+
# Returns the file information of attribute :path.
|
14
|
+
#
|
15
|
+
# @return [String] The path to the namespace file.
|
16
|
+
#
|
17
|
+
attr_reader :path
|
18
|
+
|
19
|
+
# Returns the file information of attribute :ino.
|
20
|
+
#
|
21
|
+
# @return [Integer,nil] The inode number of the namespace file. If the path is not valid, then ino is nil.
|
22
|
+
#
|
23
|
+
attr_reader :ino
|
24
|
+
|
25
|
+
# @param path [String] The path to a namespace file.
|
26
|
+
#
|
27
|
+
def initialize path
|
28
|
+
@path = path
|
29
|
+
@ino = ::File.exist?(path) ? ::File.stat(path).ino : nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module HrrRbLxns
|
2
|
+
|
3
|
+
# Represents namespace files information in /proc/PID/ns/ directory of a process.
|
4
|
+
#
|
5
|
+
# @example
|
6
|
+
# # Collects the caller process's or a specific process's namespace files information
|
7
|
+
# files = HrrRbLxns::Files.new
|
8
|
+
# files = HrrRbLxns::Files.new 12345
|
9
|
+
#
|
10
|
+
# # Each namespace file is accessible as a method or a Hash-like key
|
11
|
+
# files.uts.path # => "/proc/12345/ns/uts"
|
12
|
+
# files[:uts].path # => "/proc/12345/ns/uts"
|
13
|
+
# files["uts"].path # => "/proc/12345/ns/uts"
|
14
|
+
class Files
|
15
|
+
include Enumerable
|
16
|
+
|
17
|
+
# Returns the file information of attribute :mnt.
|
18
|
+
#
|
19
|
+
# @return [HrrRbLxns::Files::File]
|
20
|
+
#
|
21
|
+
attr_reader :mnt
|
22
|
+
|
23
|
+
# Returns the file information of attribute :uts.
|
24
|
+
#
|
25
|
+
# @return [HrrRbLxns::Files::File]
|
26
|
+
#
|
27
|
+
attr_reader :uts
|
28
|
+
|
29
|
+
# Returns the file information of attribute :ipc.
|
30
|
+
#
|
31
|
+
# @return [HrrRbLxns::Files::File]
|
32
|
+
#
|
33
|
+
attr_reader :ipc
|
34
|
+
|
35
|
+
# Returns the file information of attribute :net.
|
36
|
+
#
|
37
|
+
# @return [HrrRbLxns::Files::File]
|
38
|
+
#
|
39
|
+
attr_reader :net
|
40
|
+
|
41
|
+
# Returns the file information of attribute :pid.
|
42
|
+
#
|
43
|
+
# @return [HrrRbLxns::Files::File]
|
44
|
+
#
|
45
|
+
attr_reader :pid
|
46
|
+
|
47
|
+
# Returns the file information of attribute :pid_for_children.
|
48
|
+
#
|
49
|
+
# @return [HrrRbLxns::Files::File]
|
50
|
+
#
|
51
|
+
attr_reader :pid_for_children
|
52
|
+
|
53
|
+
# Returns the file information of attribute :user.
|
54
|
+
#
|
55
|
+
# @return [HrrRbLxns::Files::File]
|
56
|
+
#
|
57
|
+
attr_reader :user
|
58
|
+
|
59
|
+
# Returns the file information of attribute :cgroup.
|
60
|
+
#
|
61
|
+
# @return [HrrRbLxns::Files::File]
|
62
|
+
#
|
63
|
+
attr_reader :cgroup
|
64
|
+
|
65
|
+
# Returns the file information of attribute :time.
|
66
|
+
#
|
67
|
+
# @return [HrrRbLxns::Files::File]
|
68
|
+
#
|
69
|
+
attr_reader :time
|
70
|
+
|
71
|
+
# Returns the file information of attribute :time_for_children.
|
72
|
+
#
|
73
|
+
# @return [HrrRbLxns::Files::File]
|
74
|
+
#
|
75
|
+
attr_reader :time_for_children
|
76
|
+
|
77
|
+
# @param pid [Integer,String] The pid of a process to collect namespace files information. If nil, assumes that it is the caller process.
|
78
|
+
#
|
79
|
+
def initialize pid="self"
|
80
|
+
@mnt = File.new "/proc/#{pid}/ns/mnt"
|
81
|
+
@uts = File.new "/proc/#{pid}/ns/uts"
|
82
|
+
@ipc = File.new "/proc/#{pid}/ns/ipc"
|
83
|
+
@net = File.new "/proc/#{pid}/ns/net"
|
84
|
+
@pid = File.new "/proc/#{pid}/ns/pid"
|
85
|
+
@pid_for_children = File.new "/proc/#{pid}/ns/pid_for_children"
|
86
|
+
@user = File.new "/proc/#{pid}/ns/user"
|
87
|
+
@cgroup = File.new "/proc/#{pid}/ns/cgroup"
|
88
|
+
@time = File.new "/proc/#{pid}/ns/time"
|
89
|
+
@time_for_children = File.new "/proc/#{pid}/ns/time_for_children"
|
90
|
+
end
|
91
|
+
|
92
|
+
# Returns the file information of the specified key.
|
93
|
+
#
|
94
|
+
# @example
|
95
|
+
# files = HrrRbLxns::Files.new 12345
|
96
|
+
# files[:uts].path # => "/proc/12345/ns/uts"
|
97
|
+
# files["uts"].path # => "/proc/12345/ns/uts"
|
98
|
+
#
|
99
|
+
# @param key [Symbol,String] The namespace file name, which is :mnt, :uts, pid, :pid_for_children, ....
|
100
|
+
# @return [HrrRbLxns::Files::File]
|
101
|
+
#
|
102
|
+
def [] key
|
103
|
+
__send__ key
|
104
|
+
end
|
105
|
+
|
106
|
+
# Calls the given block once for each key with associated file information.
|
107
|
+
# If no block is given, an Enumerator is returned.
|
108
|
+
#
|
109
|
+
# @example
|
110
|
+
# files = HrrRbLxns::Files.new 12345
|
111
|
+
# files.each do |type, namespace_file|
|
112
|
+
# # at first iteration
|
113
|
+
# type # => :cgroup
|
114
|
+
# namespace_file.path # => "/proc/12345/ns/cgroup"
|
115
|
+
# end
|
116
|
+
#
|
117
|
+
def each
|
118
|
+
keys_with_files = [:mnt, :uts, :ipc, :net, :pid, :pid_for_children, :user, :cgroup, :time, :time_for_children].map{ |key| [key, __send__(key)] }
|
119
|
+
if block_given?
|
120
|
+
keys_with_files.each do |kv|
|
121
|
+
yield kv
|
122
|
+
end
|
123
|
+
else
|
124
|
+
keys_with_files.each
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
require "hrr_rb_lxns/files/file"
|
data/lib/hrr_rb_lxns/version.rb
CHANGED
data/lib/hrr_rb_lxns.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "hrr_rb_lxns/version"
|
2
2
|
require "hrr_rb_lxns/hrr_rb_lxns"
|
3
|
+
require "hrr_rb_lxns/files"
|
3
4
|
require "hrr_rb_mount"
|
4
5
|
|
5
6
|
# Utilities working with Linux namespaces for CRuby.
|
@@ -9,6 +10,20 @@ module HrrRbLxns
|
|
9
10
|
module Constants
|
10
11
|
end
|
11
12
|
|
13
|
+
# Collects namespace files information in /proc/PID/ns/ directory of a process.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# # Collects the caller process's or a specific process's namespace files information
|
17
|
+
# files = HrrRbLxns.files
|
18
|
+
# files = HrrRbLxns.files 12345
|
19
|
+
# files.uts.path # => "/proc/12345/ns/uts"
|
20
|
+
#
|
21
|
+
# @param pid [Integer,String] The pid of a process to collect namespace files information. If nil, assumes that it is the caller process.
|
22
|
+
# @return [HrrRbLxns::Files]
|
23
|
+
def self.files pid="self"
|
24
|
+
Files.new pid
|
25
|
+
end
|
26
|
+
|
12
27
|
# A wrapper around unshare(2) system call.
|
13
28
|
#
|
14
29
|
# @example
|
@@ -44,18 +59,26 @@ module HrrRbLxns
|
|
44
59
|
# @option options [String] :cgroup A persistent cgroup namespace to be created by bind mount.
|
45
60
|
# @option options [String] :time A persistent time namespace to be created by bind mount.
|
46
61
|
# @option options [Boolean] :fork If specified, the caller process forks after unshare.
|
62
|
+
# @option options [String,Array<String>,Array<#to_i>,Array<Array<#to_i>>] :map_uid If specified, the caller process writes UID map in /proc/PID/uid_map.
|
63
|
+
# @option options [String,Array<String>,Array<#to_i>,Array<Array<#to_i>>] :map_gid If specified, the caller process writes deny in /proc/PID/setgroups and GID map in /proc/PID/gid_map.
|
64
|
+
# @option options [Numeric,String] :monotonic If specified, writes monotonic offset in /proc/PID/timens_offsets.
|
65
|
+
# @option options [Numeric,String] :boottime If specified, writes boottime offset in /proc/PID/timens_offsets.
|
47
66
|
# @return [Integer, nil] Usually 0. If :fork is specified in options, then PID of the child process in parent, nil in child (as same as Kernel.#fork).
|
48
67
|
# @raise [ArgumentError] When given flags argument is not appropriate.
|
68
|
+
# @raise [TypeError] When map_uid and/or map_gid value is not appropriate.
|
49
69
|
# @raise [Errno::EXXX] In case unshare(2) system call failed.
|
50
70
|
def self.unshare flags, options={}
|
51
71
|
_flags = interpret_flags flags
|
52
72
|
bind_ns_files_from_child(_flags, options) do
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
__unshare__ _flags
|
73
|
+
ret = nil
|
74
|
+
map_uid_gid_from_child(_flags, options) do
|
75
|
+
ret = __unshare__ _flags
|
76
|
+
set_timens_offsets(_flags, options)
|
58
77
|
end
|
78
|
+
if fork?(options)
|
79
|
+
ret = fork
|
80
|
+
end
|
81
|
+
ret
|
59
82
|
end
|
60
83
|
end
|
61
84
|
|
@@ -109,15 +132,35 @@ module HrrRbLxns
|
|
109
132
|
_flags = interpret_flags flags
|
110
133
|
nstype_file_h = get_nstype_file_h _flags, pid, options
|
111
134
|
do_setns nstype_file_h
|
135
|
+
return 0
|
112
136
|
end
|
113
137
|
|
114
138
|
private
|
115
139
|
|
116
140
|
def self.interpret_flags arg
|
117
141
|
case arg
|
118
|
-
when Integer
|
119
|
-
|
120
|
-
|
142
|
+
when Integer
|
143
|
+
check_flags arg
|
144
|
+
arg
|
145
|
+
when String
|
146
|
+
chars_to_flags arg
|
147
|
+
else
|
148
|
+
raise TypeError, "unsupported flags: #{arg.inspect}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def self.check_flags flags
|
153
|
+
valid_flags = 0
|
154
|
+
valid_flags += NEWIPC if const_defined?(:NEWIPC)
|
155
|
+
valid_flags += NEWNS if const_defined?(:NEWNS)
|
156
|
+
valid_flags += NEWNET if const_defined?(:NEWNET)
|
157
|
+
valid_flags += NEWPID if const_defined?(:NEWPID)
|
158
|
+
valid_flags += NEWUTS if const_defined?(:NEWUTS)
|
159
|
+
valid_flags += NEWUSER if const_defined?(:NEWUSER)
|
160
|
+
valid_flags += NEWCGROUP if const_defined?(:NEWCGROUP)
|
161
|
+
valid_flags += NEWTIME if const_defined?(:NEWTIME)
|
162
|
+
unless (flags - (flags & valid_flags)).zero?
|
163
|
+
raise ArgumentError, "unsupported flags are set"
|
121
164
|
end
|
122
165
|
end
|
123
166
|
|
@@ -214,12 +257,133 @@ module HrrRbLxns
|
|
214
257
|
end
|
215
258
|
end
|
216
259
|
|
260
|
+
def self.map_uid_gid? flags, options
|
261
|
+
const_defined?(:NEWUSER) && (flags & NEWUSER).zero?.! && (options.has_key?(:map_uid) || options.has_key?(:map_gid))
|
262
|
+
end
|
263
|
+
|
264
|
+
# This method calls fork and the child process writes into /proc/PID/uid_map, /proc/PID/gid_map, and /proc/PID/setgroups.
|
265
|
+
def self.map_uid_gid_from_child flags, options
|
266
|
+
if map_uid_gid? flags, options
|
267
|
+
pid_to_map = Process.pid
|
268
|
+
IO.pipe do |io_r, io_w|
|
269
|
+
if pid = fork
|
270
|
+
begin
|
271
|
+
ret = yield
|
272
|
+
rescue Exception
|
273
|
+
Process.kill "KILL", pid
|
274
|
+
Process.waitpid pid
|
275
|
+
raise
|
276
|
+
else
|
277
|
+
io_w.write "1"
|
278
|
+
io_w.close
|
279
|
+
Process.waitpid pid
|
280
|
+
raise Marshal.load(io_r.read) unless $?.to_i.zero?
|
281
|
+
ret
|
282
|
+
end
|
283
|
+
else
|
284
|
+
begin
|
285
|
+
io_r.read 1
|
286
|
+
map_uid_gid options, pid_to_map
|
287
|
+
rescue Exception => e
|
288
|
+
io_w.write Marshal.dump(e)
|
289
|
+
exit! false
|
290
|
+
else
|
291
|
+
exit! true
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
else
|
296
|
+
yield
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
def self.map_uid_gid options, pid
|
301
|
+
if options.has_key?(:map_uid)
|
302
|
+
write_id_map options[:map_uid], pid, "uid"
|
303
|
+
end
|
304
|
+
if options.has_key?(:map_gid)
|
305
|
+
deny_setgroups pid
|
306
|
+
write_id_map options[:map_gid], pid, "gid"
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
def self.write_id_map mapping, pid, type
|
311
|
+
path = "/proc/#{pid}/#{type}_map"
|
312
|
+
_mapping = case mapping
|
313
|
+
when String # "0 0 1", "0 0 1\n1 10000 1000\n"
|
314
|
+
mapping.chomp
|
315
|
+
when Array
|
316
|
+
if mapping.all?{|e| e.respond_to?(:match?) && e.match?(/^\d+ \d+ \d+$/)} # ["0 0 1", "1 10000 1000"]
|
317
|
+
mapping.join("\n")
|
318
|
+
elsif mapping.all?{|e| e.respond_to?(:to_i)} # [0, 0, 1], ["0", "0", "1"]
|
319
|
+
mapping.map(&:to_i).join(" ")
|
320
|
+
elsif mapping.all?{|e| e.respond_to?(:all?) && e.all?{ |e2| e2.respond_to?(:to_i)}} # [[0, 0, 1], ["1", "10000", "1000"]]
|
321
|
+
mapping.map{|e| e.map(&:to_i).join(" ")}.join("\n")
|
322
|
+
else
|
323
|
+
raise TypeError, "map_#{type}"
|
324
|
+
end
|
325
|
+
else
|
326
|
+
raise TypeError, "map_#{type}"
|
327
|
+
end
|
328
|
+
File.open(path, "w") do |f|
|
329
|
+
f.puts _mapping
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
def self.deny_setgroups pid
|
334
|
+
File.open("/proc/#{pid}/setgroups", "w") do |f|
|
335
|
+
f.puts "deny"
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def self.set_timens_offsets? flags, options
|
340
|
+
const_defined?(:NEWTIME) && (flags & NEWTIME).zero?.! && (options.has_key?(:monotonic) || options.has_key?(:boottime))
|
341
|
+
end
|
342
|
+
|
343
|
+
def self.set_timens_offsets(flags, options)
|
344
|
+
if set_timens_offsets? flags, options
|
345
|
+
File.open("/proc/self/timens_offsets", "w") do |f|
|
346
|
+
[
|
347
|
+
[MONOTONIC, :monotonic],
|
348
|
+
[BOOTTIME, :boottime ],
|
349
|
+
].each do |clk_id, key|
|
350
|
+
if options.has_key? key
|
351
|
+
offset_secs = options[key].to_i
|
352
|
+
offset_nanosecs = ((Rational(options[key]) - offset_secs) * 10**9).to_i
|
353
|
+
f.puts "#{clk_id} #{offset_secs} #{offset_nanosecs}"
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
217
360
|
def self.do_setns nstype_file_h
|
218
|
-
nstype_file_h.
|
219
|
-
|
220
|
-
|
361
|
+
list_without_user = nstype_file_h.keys - [NEWUSER]
|
362
|
+
success = {}
|
363
|
+
error = {}
|
364
|
+
nstype_fileobj_h = {}
|
365
|
+
begin
|
366
|
+
nstype_file_h.each do |nstype, file|
|
367
|
+
nstype_fileobj_h[nstype] = File.open(file, File::RDONLY)
|
221
368
|
end
|
222
|
-
|
369
|
+
(list_without_user + [NEWUSER] + list_without_user).each do |nstype|
|
370
|
+
next unless nstype_file_h.has_key? nstype
|
371
|
+
begin
|
372
|
+
next if success.has_key? nstype
|
373
|
+
fileobj = nstype_fileobj_h[nstype]
|
374
|
+
__setns__ fileobj.fileno, nstype
|
375
|
+
rescue
|
376
|
+
raise if error.has_key? nstype
|
377
|
+
error[nstype] = true
|
378
|
+
else
|
379
|
+
success[nstype] = true
|
380
|
+
end
|
381
|
+
end
|
382
|
+
ensure
|
383
|
+
nstype_fileobj_h.each do |nstype, fileobj|
|
384
|
+
fileobj.close
|
385
|
+
end
|
386
|
+
end
|
223
387
|
end
|
224
388
|
|
225
389
|
def self.get_nstype_file_h flags, pid, options
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hrr_rb_lxns
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- hirura
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-05-
|
11
|
+
date: 2020-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hrr_rb_mount
|
@@ -47,6 +47,8 @@ files:
|
|
47
47
|
- ext/hrr_rb_lxns/hrr_rb_lxns.h
|
48
48
|
- hrr_rb_lxns.gemspec
|
49
49
|
- lib/hrr_rb_lxns.rb
|
50
|
+
- lib/hrr_rb_lxns/files.rb
|
51
|
+
- lib/hrr_rb_lxns/files/file.rb
|
50
52
|
- lib/hrr_rb_lxns/version.rb
|
51
53
|
homepage: https://github.com/hirura/hrr_rb_lxns
|
52
54
|
licenses:
|