1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
implement Ns;
#
# Copyright © 2003 Vita Nuova Holdings Limited. All rights reserved.
#
include "sys.m";
sys: Sys;
include "draw.m";
include "arg.m";
include "sh.m";
sh: Sh;
ns : list of string;
Ns: module {
init: fn(nil: ref Draw->Context, argv: list of string);
};
init(nil: ref Draw->Context, argv: list of string)
{
sys = load Sys Sys->PATH;
if (sys == nil)
badmod(Sys->PATH);
sh = load Sh Sh->PATH;
if (sh == nil)
badmod(Sh->PATH);
# sys->pctl(sys->FORKNS, nil);
sys->unmount(nil, "/n/remote");
arg := load Arg Arg->PATH;
if (arg == nil)
badmod(Arg->PATH);
arg->init(argv);
arg->setusage("ns [-v] [-r relpath] paths...");
verbose := 0;
relpath := "";
while ((opt := arg->opt()) != 0) {
case opt {
'v' =>
verbose = 1;
'r' =>
relpath = arg->earg();
if (relpath == nil)
arg->usage();
if (relpath[len relpath - 1] != '/')
relpath[len relpath] = '/';
* =>
arg->usage();
}
}
ns = arg->argv();
arg = nil;
if (ns == nil) {
sys->fprint(fdout(), "error no namespace selected\n");
exit;
}
spawn buildns(relpath, verbose);
}
fdout(): ref sys->FD
{
return sys->fildes(1);
}
buildns(relpath: string, verbose: int)
{
# sys->pctl(sys->FORKNS, nil);
if (sh->run(nil, "memfs"::"/n/remote"::nil) != nil) {
sys->fprint(fdout(), "error MemFS mount failed\n");
exit;
}
for (tmpl := ns; tmpl != nil; tmpl = tl tmpl) {
nspath := hd tmpl;
if (nspath[len nspath - 1] != '/')
nspath[len nspath] = '/';
bindpath := nspath;
if (bindpath[:len relpath] == relpath) {
bindpath = "/n/remote/"+bindpath[len relpath:];
if (createdir(bindpath) != -1) {
if (sys->bind(nspath, bindpath, sys->MBEFORE | sys->MCREATE) == -1) {
if (sys->bind(nspath, bindpath, sys->MBEFORE) == -1)
sys->fprint(fdout(), "error bind failed %s: %r\n",bindpath);
else if (verbose)
sys->fprint(fdout(), "data nspath %s\n", nspath);
}
else if (verbose)
sys->fprint(fdout(), "data nspath %s\n", nspath);
}
else
sys->fprint(fdout(), "error create failed %s\n",bindpath);
}
}
spawn exportns();
}
exportns()
{
sys->export(sys->fildes(0), "/n/remote", sys->EXPWAIT);
}
createdir(path: string): int
{
(nil, lst) := sys->tokenize(path, "/");
npath := "";
for (; lst != nil; lst = tl lst) {
(n, nil) := sys->stat(npath + "/" + hd lst);
if (n == -1) {
fd := sys->create(npath + "/" + hd lst, sys->OREAD, 8r777 | sys->DMDIR);
if (fd == nil)
return -1;
}
npath += "/" + hd lst;
}
return 0;
}
badmod(path: string)
{
sys->fprint(fdout(), "error Ns: failed to load: %s\n",path);
exit;
}
|