hrr_rb_lxns 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|