820 lines
34 KiB
JavaScript
820 lines
34 KiB
JavaScript
/**
|
|
** ==============================
|
|
** O O O OOOO
|
|
** O O O O O O
|
|
** O O O O O O
|
|
** OOOO OOOO O OOO OOOO
|
|
** O O O O O O O
|
|
** O O O O O O O
|
|
** OOOO OOOO O O OOOO
|
|
** ==============================
|
|
** Dr. Stefan Bosse http://www.bsslab.de
|
|
**
|
|
** COPYRIGHT: THIS SOFTWARE, EXECUTABLE AND SOURCE CODE IS OWNED
|
|
** BY THE AUTHOR(S).
|
|
** THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED,
|
|
** MODIFIED, OR OTHERWISE USED IN A CONTEXT
|
|
** OUTSIDE OF THE SOFTWARE SYSTEM.
|
|
**
|
|
** $AUTHORS: Stefan Bosse
|
|
** $INITIAL: (C) 2006-2017 bLAB
|
|
** $CREATED: 13-6-15 by sbosse.
|
|
** $VERSION: 1.1.6
|
|
**
|
|
** $INFO:
|
|
**
|
|
** DOS: Amoeba Shell Interpreter Module
|
|
**
|
|
* TODO: merge rootdir/workdir variables in env/dns objects
|
|
**
|
|
** $ENDOFINFO
|
|
*/
|
|
"use strict";
|
|
var Io = Require('com/io');
|
|
//Io.trace_open('/tmp/shell.trace');
|
|
|
|
var Net = Require('dos/network');
|
|
var Sch = Require('dos/scheduler');
|
|
var Buf = Require('dos/buf');
|
|
var Conn = Require('dos/connection');
|
|
var Rpc = Require('dos/rpc');
|
|
var Std = Require('dos/std');
|
|
var Router = Require('dos/router');
|
|
var util = Require('util');
|
|
var Comp = Require('com/compat');
|
|
var assert = Comp.assert;
|
|
var String = Comp.string;
|
|
var Array = Comp.array;
|
|
var Perv = Comp.pervasives;
|
|
var Printf = Comp.printf;
|
|
var Filename = Comp.filename;
|
|
var Status = Net.Status;
|
|
var Command = Net.Command;
|
|
var Fs = Require('fs');
|
|
var Dns = Require('dos/dns');
|
|
var Afs = Require('dos/afs');
|
|
var Cs = Require('dos/capset');
|
|
|
|
/**
|
|
* @param privhostport
|
|
* @param pubhostport
|
|
* @param hostname
|
|
* @param workdir
|
|
* @param rootdir
|
|
* @param workpath
|
|
* @param echo
|
|
* @constructor
|
|
*
|
|
*/
|
|
var env = function (privhostport,pubhostport,hostname,workdir,rootdir,workpath,echo) {
|
|
var workenv = Io.getenv('WORKCAP','');
|
|
var rootenv = Io.getenv('ROOTCAP','');
|
|
/*
|
|
** This host!
|
|
*/
|
|
this.privhostport = privhostport||Net.uniqport();
|
|
this.pubhostport = pubhostport||Net.prv2pub(this.privhostport);
|
|
this.hostname = hostname||Net.Print.port(this.pubhostport);
|
|
/*
|
|
** Working environment. If not defined, working dir = resolved root directory.
|
|
* Note: workdir must be kept in sync with dns.env.workdir!
|
|
*/
|
|
if (workdir) this.workdir = workdir;
|
|
else if (!String.empty(workenv)) this.workdir=workenv;
|
|
else this.workdir=undefined;
|
|
|
|
/*
|
|
** 1. A DNS directory capability (textual representation)
|
|
** 2. A Host Server port (rootdir is resolved by a DNS_GETROOTCAP request)
|
|
* Note: rootdir must be kept in sync with dns.env.rootdir!
|
|
*/
|
|
if (rootdir) this.rootdir = rootdir;
|
|
else if (!String.empty(rootenv)) this.rootdir=rootenv;
|
|
else this.rootdir=undefined;
|
|
|
|
this.defafs=undefined;
|
|
|
|
this.afs_colmask = Afs.AFS_DEFAULT_RIGHTS;
|
|
this.dns_colmask = Dns.DNS_DEFAULT_RIGHTS;
|
|
|
|
this.workpath = workpath||'/';
|
|
this.echo=echo||false;
|
|
this.parentdir=[];
|
|
|
|
this.script=[];
|
|
this.in_script=false;
|
|
|
|
this.prompt = function () {
|
|
return this.hostname+this.workpath+' > ';
|
|
};
|
|
|
|
/*
|
|
** Current working directory row names
|
|
*/
|
|
this.workrows=[];
|
|
};
|
|
|
|
|
|
function fail(msg) {
|
|
Io.stderr('[JASH]: Fatal error: '+msg+'\n');
|
|
process.exit(0);
|
|
}
|
|
function out(msg) {
|
|
Io.stdout('[JASH]: '+msg+'\n');
|
|
}
|
|
function warn(msg) {
|
|
Io.stderr('[JASH]: Warning: '+msg+'\n');
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {rpcint} rpc
|
|
* @param {scheduler} scheduler
|
|
* @param {env} env
|
|
* @constructor
|
|
* @typedef {{rpc,env,scheduler,std,dns,afs,cs}} ash~obj
|
|
* @see ash~obj
|
|
*/
|
|
var ash = function(rpc,scheduler,env) {
|
|
this.rpc=rpc;
|
|
this.env=env;
|
|
this.scheduler=scheduler;
|
|
this.std = Std.StdInt(rpc);
|
|
this.dns = Dns.DnsInt(rpc);
|
|
this.afs = Afs.AfsInt(rpc);
|
|
this.cs = Cs.CsInt(rpc);
|
|
/*
|
|
** Externally supplied action handlers
|
|
*/
|
|
this.actions = [];
|
|
|
|
this.dns.env.workdir = env.workdir;
|
|
};
|
|
|
|
/** Execute a shell command. Installs a scheduler block only!
|
|
*
|
|
* @param {string} cmdline
|
|
* @param {function} [refresh] shell update callback (only called if there was no output)
|
|
*/
|
|
ash.prototype.exec = function(cmdline,refresh) {
|
|
var self=this;
|
|
var env=this.env;
|
|
var scheduler=this.scheduler;
|
|
var StdInt = this.std;
|
|
var CsInt = this.cs;
|
|
var DnsInt = this.dns;
|
|
var stat=Status.STD_OK;
|
|
|
|
|
|
Sch.ScheduleBlock([
|
|
function () {
|
|
var path;
|
|
var line;
|
|
|
|
if (env.echo) Io.out(cmdline);
|
|
var args1 = Array.filter(String.split(' ', cmdline), function (str) {
|
|
return str != '';
|
|
});
|
|
/*
|
|
** Glue strings again...
|
|
*/
|
|
var args = [];
|
|
var curarg = '';
|
|
var instr = false;
|
|
Array.iter(args1, function (arg) {
|
|
if (!instr && String.get(arg, 0) == '"') {
|
|
instr = true;
|
|
curarg = String.trim(arg, 1, 0);
|
|
} else if (instr) {
|
|
if (String.get(arg,arg.length-1)=='"') {
|
|
instr=false;
|
|
curarg = curarg + ' ' +String.trim(arg,0,1);
|
|
args.push(curarg);
|
|
}
|
|
else curarg = curarg + ' ' + arg;
|
|
} else args.push(arg);
|
|
});
|
|
|
|
if (!Array.empty(args)) String.match(args[0], [
|
|
/*
|
|
** CD
|
|
*/
|
|
['cd', function () {
|
|
var cs;
|
|
var stat;
|
|
var dir;
|
|
var rownum;
|
|
var row;
|
|
var help;
|
|
var info;
|
|
|
|
Array.iter(args, function (arg, index) {
|
|
if (index > 0) {
|
|
String.match(arg, [
|
|
['-h', function () {
|
|
help = true;
|
|
}]
|
|
])
|
|
}
|
|
});
|
|
if (args.length == 1) help = true;
|
|
if (help) {
|
|
Io.out('usage:\n cd <relative path>|<absolute path>| #<current working dir. row number>');
|
|
}
|
|
else if (args.length == 2) {
|
|
path = args[1];
|
|
env.workrows=[];
|
|
if (Filename.is_relative(path) && env.workdir != undefined) {
|
|
if (String.get(path, 0) == '#') {
|
|
rownum = Perv.int_of_string(String.trim(path, 1, 0));
|
|
if (isNaN(rownum)) throw Status.STD_ARGBAD;
|
|
/*
|
|
** Select the n-th row of the current working directory.
|
|
*/
|
|
Sch.ScheduleBlock([
|
|
function () {
|
|
DnsInt.dns_list(env.workdir, function (_stat, _dir) {
|
|
dir = _dir;
|
|
stat = _stat;
|
|
});
|
|
},
|
|
function () {
|
|
if (stat != Status.STD_OK) throw stat;
|
|
if (rownum >= dir.di_rows.length) throw Status.STD_NOTFOUND;
|
|
row = dir.di_rows[rownum];
|
|
DnsInt.dns_lookup(env.workdir, row.de_name, function (_stat, _cs) {
|
|
stat = _stat;
|
|
cs = _cs;
|
|
})
|
|
},
|
|
function () {
|
|
if (stat != Status.STD_OK) throw stat;
|
|
StdInt.std_info(CsInt.cs_to_cap(cs),function (_stat,_info) {
|
|
stat = _stat;
|
|
info = _info;
|
|
});
|
|
},
|
|
function () {
|
|
if (stat != Status.STD_OK) throw stat;
|
|
if (String.empty(info) || String.get(info,0)!='/') throw Status.STD_DENIED;
|
|
env.workpath = Filename.path_normalize(env.workpath + '/' + row.de_name);
|
|
Array.push(env.parentdir, env.workdir);
|
|
env.workdir = cs;
|
|
self.dns.env.workdir = env.workdir;
|
|
if (refresh) refresh();
|
|
}
|
|
], function (e) {
|
|
if (typeof e != 'number') Io.inspect(e);
|
|
else Io.out(Status.print(e));
|
|
})
|
|
} else if (String.equal(path, '..')) {
|
|
if (Array.empty(env.parentdir)) {
|
|
Io.out('No parent directory defined.');
|
|
} else {
|
|
env.workpath = Filename.path_normalize(env.workpath + '/..');
|
|
env.workdir = Array.pop(env.parentdir);
|
|
self.dns.env.workdir = env.workdir;
|
|
if (refresh) refresh();
|
|
}
|
|
} else {
|
|
var pathelem = String.split('/', path);
|
|
if (pathelem.length == 1) {
|
|
Sch.ScheduleBlock([
|
|
function () {
|
|
DnsInt.dns_lookup(env.workdir, pathelem[0], function (_stat, _cs) {
|
|
stat = _stat;
|
|
cs = _cs;
|
|
})
|
|
},
|
|
function () {
|
|
if (stat != Status.STD_OK) throw stat;
|
|
StdInt.std_info(CsInt.cs_to_cap(cs),function (_stat,_info) {
|
|
stat = _stat;
|
|
info = _info;
|
|
});
|
|
},
|
|
function () {
|
|
if (stat != Status.STD_OK) throw stat;
|
|
if (String.empty(info) || String.get(info,0)!='/') throw Status.STD_DENIED;
|
|
|
|
env.workpath = Filename.path_normalize(env.workpath + '/' + pathelem[0]);
|
|
Array.push(env.parentdir, env.workdir);
|
|
env.workdir = cs;
|
|
self.dns.env.workdir = env.workdir;
|
|
if (refresh) refresh();
|
|
|
|
}
|
|
], function (e) {
|
|
if (typeof e != 'number') Io.inspect(e);
|
|
else Io.out(Status.print(e));
|
|
})
|
|
}
|
|
}
|
|
} else if (!Filename.is_relative(path)) {
|
|
Io.out('Not implemented.');
|
|
} else {
|
|
Io.out('No working directory defined.');
|
|
}
|
|
}
|
|
}],
|
|
/*
|
|
** DEL
|
|
*/
|
|
['del', function () {
|
|
var cs;
|
|
var stat;
|
|
var dir;
|
|
var rownum;
|
|
var row;
|
|
var help;
|
|
var destroy;
|
|
var rowcs;
|
|
var i;
|
|
|
|
if (args.length == 1) help = true;
|
|
|
|
args = Array.filter(args, function (arg, index) {
|
|
if (index > 0) {
|
|
var use=false;
|
|
String.match(arg, [
|
|
['-h', function () {
|
|
help = true;
|
|
use = false;
|
|
}],
|
|
['-d', function () {
|
|
destroy = true;
|
|
use = false;
|
|
}],
|
|
function () {
|
|
use = true;
|
|
}
|
|
]);
|
|
return use;
|
|
} else return false;
|
|
});
|
|
if (help) {
|
|
Io.out('usage:\n del [-d] <relative path>|<absolute path>');
|
|
}
|
|
else {
|
|
if (args.length == 1) {
|
|
var path = args[0];
|
|
if (Filename.is_relative(path) && env.workdir != undefined) {
|
|
var pathelem = String.split('/', path);
|
|
if (pathelem.length == 1) {
|
|
Sch.ScheduleBlock([
|
|
function () {
|
|
DnsInt.dns_lookup(env.workdir, pathelem[0], function (_stat,_cs) {
|
|
stat=_stat;
|
|
rowcs=_cs;
|
|
})
|
|
},
|
|
function () {
|
|
if (stat==Status.STD_OK) DnsInt.dns_delete(env.workdir, pathelem[0],
|
|
function (_stat) {
|
|
stat = _stat;
|
|
})
|
|
},
|
|
function () {
|
|
if (stat==Status.STD_OK && destroy) {
|
|
Sch.ScheduleLoop(function (index) {
|
|
i=index;
|
|
return index < rowcs.cs_final;
|
|
}, [
|
|
function () {
|
|
StdInt.std_destroy(rowcs.cs_suite[i].s_object,function (_stat) {
|
|
Io.out('Destroyed '+Net.Print.capability(rowcs.cs_suite[i].s_object)+ ': '+
|
|
Status.print(_stat));
|
|
})
|
|
}
|
|
])
|
|
}
|
|
},
|
|
function () {
|
|
if (stat != Status.STD_OK) Io.out(Status.print(stat));
|
|
else {
|
|
env.workrows=[];
|
|
if (refresh) refresh();
|
|
}
|
|
|
|
}
|
|
])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}],
|
|
/*
|
|
** DIR
|
|
*/
|
|
['dir', function () {
|
|
var long = false;
|
|
var info = false;
|
|
var help = false;
|
|
var pcap = false;
|
|
var paths = [];
|
|
var stat;
|
|
var dir;
|
|
var len;
|
|
|
|
function print_dir(dir) {
|
|
env.workrows=[];
|
|
DnsInt.dns_list(dir, function (_stat, _dir) {
|
|
if (_stat == Status.STD_OK) {
|
|
if (long && !info) {
|
|
line = Printf.sprintf2([
|
|
['%35s', 'Name'],
|
|
' ',
|
|
['%12s', ' Time'],
|
|
' ',
|
|
['%10s', 'Rights'],
|
|
' ',
|
|
['%3s', 'Row']
|
|
]);
|
|
Io.out(line);
|
|
Io.out('------------------------------------------------------------------');
|
|
Array.iter(_dir.di_rows, function (row, index) {
|
|
var cols = '';
|
|
Array.iter(row.de_columns, function (col, index) {
|
|
if (index > 0) cols = cols + '-';
|
|
cols = cols + String.format_hex(col, 2);
|
|
});
|
|
env.workrows.push(row.de_name);
|
|
line = Printf.sprintf2([
|
|
['%35s', row.de_name],
|
|
' ',
|
|
['%12d', row.de_time],
|
|
' ',
|
|
['%10s', cols],
|
|
' ',
|
|
['%3d', index]
|
|
]);
|
|
Io.out(line);
|
|
});
|
|
} else if (info || pcap) {
|
|
var rowlen = _dir.di_rows.length;
|
|
var row;
|
|
var index = 0;
|
|
var cs = undefined;
|
|
if (info)
|
|
line = Printf.sprintf2([
|
|
['%35s', 'Name'],
|
|
' ',
|
|
['%30s', 'Info']]);
|
|
else
|
|
line = Printf.sprintf2([
|
|
['%35s', 'Name'],
|
|
' ',
|
|
['%30s', 'Capability']]);
|
|
|
|
|
|
Io.out(line);
|
|
Io.out('------------------------------------------------------------------');
|
|
|
|
Sch.ScheduleLoop(function () {
|
|
return index < rowlen;
|
|
}, [
|
|
function () {
|
|
row = _dir.di_rows[index];
|
|
DnsInt.dns_lookup(_dir.di_capset, row.de_name, function (_stat, _cs) {
|
|
stat = _stat;
|
|
cs = _cs;
|
|
})
|
|
},
|
|
function () {
|
|
index++;
|
|
if (stat != Status.STD_OK) {
|
|
line = Printf.sprintf2([
|
|
['%35s', row.de_name],
|
|
' ',
|
|
['%30s', Status.print(stat)]
|
|
]);
|
|
Io.out(line);
|
|
} else Sch.ScheduleBlock([
|
|
function () {
|
|
if (info)
|
|
StdInt.std_info(CsInt.cs_to_cap(cs), function (_stat, _infoline) {
|
|
env.workrows.push(row.de_name);
|
|
|
|
line = Printf.sprintf2([
|
|
['%35s', row.de_name],
|
|
' ',
|
|
['%30s', (_stat == Status.STD_OK ? _infoline : Status.print(_stat))]
|
|
]);
|
|
Io.out(line);
|
|
});
|
|
else {
|
|
env.workrows.push(row.de_name);
|
|
|
|
line = Printf.sprintf2([
|
|
['%35s', row.de_name],
|
|
' ',
|
|
['%30s', (Net.Print.capability(CsInt.cs_to_cap(cs)))]
|
|
]);
|
|
Io.out(line);
|
|
}
|
|
}
|
|
])
|
|
|
|
}
|
|
])
|
|
} else {
|
|
line = '';
|
|
Array.iter(_dir.di_rows, function (row, index) {
|
|
env.workrows.push(row.de_name);
|
|
if (index > 0) line = line + ' ';
|
|
line = line + row.de_name;
|
|
});
|
|
if (String.empty(line)) line='(Empty)';
|
|
Io.out(line);
|
|
}
|
|
} else {
|
|
Io.out(Status.print(_stat));
|
|
}
|
|
})
|
|
}
|
|
|
|
Array.iter(args, function (arg, index) {
|
|
if (index > 0) {
|
|
String.match(arg, [
|
|
['-l', function () {
|
|
long = true;
|
|
}],
|
|
['-i', function () {
|
|
info = true;
|
|
}],
|
|
['-c', function () {
|
|
pcap = true;
|
|
}],
|
|
['-h', function () {
|
|
help = true;
|
|
}],
|
|
function () {
|
|
if (arg != '') paths.push(arg);
|
|
}
|
|
])
|
|
}
|
|
});
|
|
if (help) {
|
|
Io.out('usage:\n'+
|
|
' dir [-l (long) -i (info) -h (help) -c (print capability)]\n' +
|
|
' [<path1>] [<path2> ..]');
|
|
}
|
|
else {
|
|
if (Array.empty(paths) && env.workdir != undefined) {
|
|
print_dir(env.workdir);
|
|
} else if (!Array.empty(paths)) {
|
|
len = paths.length;
|
|
Sch.ScheduleLoop(function (index) {
|
|
path = paths[index];
|
|
return index < len;
|
|
}, [
|
|
function () {
|
|
DnsInt.dns_lookup(env.rootdir, path, function (_stat, _cs, rest) {
|
|
stat = _stat;
|
|
dir = _cs;
|
|
})
|
|
},
|
|
function () {
|
|
if (stat == Status.STD_OK) {
|
|
print_dir(dir);
|
|
} else {
|
|
Io.out(Status.print(stat));
|
|
}
|
|
}
|
|
])
|
|
} else {
|
|
Io.out(Status.print(Status.STD_NOTNOW));
|
|
}
|
|
}
|
|
}],
|
|
/*
|
|
** MKDIR
|
|
*/
|
|
['mkdir', function () {
|
|
var cs;
|
|
var stat;
|
|
var dir;
|
|
var rownum;
|
|
var row;
|
|
var help;
|
|
|
|
Array.iter(args, function (arg, index) {
|
|
if (index > 0) {
|
|
String.match(arg, [
|
|
['-h', function () {
|
|
help = true;
|
|
}]
|
|
])
|
|
}
|
|
});
|
|
if (args.length == 1) help = true;
|
|
if (help) {
|
|
Io.out('usage:\n mkdir <relative path>|<absolute path>');
|
|
}
|
|
else {
|
|
if (args.length == 2) {
|
|
var path = args[1];
|
|
if (Filename.is_relative(path) && env.workdir != undefined) {
|
|
var pathelem = String.split('/', path);
|
|
if (pathelem.length == 1) {
|
|
Sch.ScheduleBlock([
|
|
function () {
|
|
DnsInt.dns_create(env.workdir, Dns.DNS_DEFAULT_COLS, function (_stat, _cs) {
|
|
stat = _stat;
|
|
cs = _cs;
|
|
})
|
|
},
|
|
function () {
|
|
if (stat != Status.STD_OK) Io.out(Status.print(stat));
|
|
else DnsInt.dns_append(env.workdir, pathelem[0], cs, Dns.DNS_DEFAULT_RIGHTS,
|
|
function (_stat) {
|
|
stat = _stat;
|
|
})
|
|
},
|
|
function () {
|
|
if (stat != Status.STD_OK) Io.out(Status.print(stat));
|
|
else if (refresh) refresh();
|
|
|
|
}
|
|
])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}],
|
|
['exit', function () {
|
|
throw Status.STD_INTR;
|
|
}],
|
|
['$ROOT', function () {
|
|
Io.out(Net.Print.capability(CsInt.cs_to_cap(env.rootdir)));
|
|
}],
|
|
function (val) {
|
|
var action = Array.find(self.actions,function (action) {
|
|
return (String.equal(action[0],val));
|
|
});
|
|
if (action!=undefined) {
|
|
var fun=action[1];
|
|
fun(args);
|
|
}
|
|
else Io.out('Unknown command '+val);
|
|
}
|
|
]);
|
|
}
|
|
],function (e) {
|
|
if (typeof e != 'number') {
|
|
Io.out('[SHELL] uncaught exception:');
|
|
Io.printstack(e,'Ash.exec');
|
|
}
|
|
else if (e != Status.STD_INTR) {
|
|
Io.out('[SHELL] uncaught error:');
|
|
Io.out(Status.print(e));
|
|
}
|
|
if (!env.in_script) Io.out('\nHave a great day!');
|
|
Io.exit(0);
|
|
});
|
|
};
|
|
|
|
|
|
ash.prototype.register_action = function (name,fun) {
|
|
this.actions.push([name,fun])
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @param {string} file
|
|
* @param {function((Status.STD_OK|*),(buffer|undefined))} callback
|
|
*/
|
|
ash.prototype.readfile = function(file,callback){
|
|
var cap,stat;
|
|
var afs = this.afs;
|
|
var dns = this.dns;
|
|
var cs = this.cs;
|
|
var fcs,size;
|
|
var env = this.env;
|
|
var buf=Buf.Buffer();
|
|
|
|
Sch.ScheduleBlock([
|
|
function () {
|
|
dns.dns_lookup(env.workdir,file,function (_stat,_cs) {
|
|
stat=_stat;
|
|
fcs=_cs;
|
|
});
|
|
},
|
|
function () {
|
|
if (stat!=Status.STD_OK) throw stat;
|
|
/*
|
|
** Create file
|
|
*/
|
|
cap=cs.cs_to_cap(fcs);
|
|
afs.afs_size(cap,function (_stat,_size){
|
|
stat=_stat;
|
|
size=_size;
|
|
})
|
|
},
|
|
function () {
|
|
if (stat!=Status.STD_OK) throw stat;
|
|
/*
|
|
** Create file
|
|
*/
|
|
afs.afs_read(cap,buf,0,size,function (_stat,_n){
|
|
stat=_stat;
|
|
})
|
|
},
|
|
function () {
|
|
if (stat!=Status.STD_OK) throw stat;
|
|
callback(stat,buf);
|
|
}
|
|
], function(e) {
|
|
if (typeof e == 'number') callback(e,undefined); else {
|
|
Io.printstack(e,'ash.readfile');
|
|
callback(Status.STD_SYSERR,undefined);
|
|
}
|
|
})
|
|
};
|
|
|
|
/** Store a file in the default AFS and append capability to current working directory.
|
|
*
|
|
* @param {string} file
|
|
* @param {buffer} buf
|
|
* @param {function((Status.STD_OK|*),(capability|undefined))} callback
|
|
*/
|
|
ash.prototype.writefile = function(file,buf,callback){
|
|
var size = buf.data.length;
|
|
var afs = this.afs;
|
|
var dns = this.dns;
|
|
var std = this.std;
|
|
var cs = this.cs;
|
|
var self = this;
|
|
var env = this.env;
|
|
var cap,stat;
|
|
|
|
if (size == 0) callback(Status.STD_ARGBAD,undefined);
|
|
else if (env.defafs==undefined) callback(Status.STD_NOTNOW,undefined);
|
|
else Sch.ScheduleBlock([
|
|
function () {
|
|
/*
|
|
** Create file
|
|
*/
|
|
afs.afs_create(env.defafs,buf,size,Afs.AFS_SAFETY,function (_stat,_cap){
|
|
stat=_stat;
|
|
cap=_cap;
|
|
})
|
|
},
|
|
function () {
|
|
if (stat!=Status.STD_OK) throw stat;
|
|
/*
|
|
** Append file to current working directory
|
|
*/
|
|
dns.dns_append(dns.env.workdir,file,cs.cs_singleton(cap),env.afs_colmask,function(_stat) {
|
|
stat=_stat;
|
|
})
|
|
},
|
|
function () {
|
|
if (stat!=Status.STD_OK) {
|
|
std.std_destroy(cap,function (_stat) {
|
|
Io.out('Destroyed: '+Net.Print.capability(cap)+ ' '+Status.print(_stat));
|
|
})
|
|
}
|
|
},
|
|
function () {
|
|
callback(stat,cap);
|
|
}
|
|
], function(e) {
|
|
if (typeof e == 'number') callback(e,undefined); else {
|
|
Io.printstack(e,'ash.writefile');
|
|
callback(Status.STD_SYSERR,undefined);
|
|
}
|
|
})
|
|
};
|
|
|
|
module.exports = {
|
|
/**
|
|
*
|
|
* @param [privhostport]
|
|
* @param [pubhostport]
|
|
* @param [hostname]
|
|
* @param [workdir]
|
|
* @param [rootdir]
|
|
* @param [workpath]
|
|
* @param [echo]
|
|
* @returns {env}
|
|
*/
|
|
Env: function(privhostport,pubhostport,hostname,workdir,rootdir,workpath,echo) {
|
|
var obj = new env(privhostport,pubhostport,hostname,workdir,rootdir,workpath,echo);
|
|
Object.preventExtensions(obj);
|
|
return obj;
|
|
},
|
|
/**
|
|
*
|
|
* @param rpc
|
|
* @param scheduler
|
|
* @param env
|
|
* @returns {ash}
|
|
*/
|
|
Ash: function (rpc,scheduler,env) {
|
|
var obj = new ash(rpc,scheduler,env);
|
|
Object.preventExtensions(obj);
|
|
return obj;
|
|
}
|
|
};
|