ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/demo/ns/ns.b/
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;
}