940 lines
29 KiB
JavaScript
940 lines
29 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
|
|
** ==============================
|
|
** BSSLAB, 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: 31-3-15 by sbosse.
|
|
** $VERSION: 1.1.8
|
|
**
|
|
** $INFO:
|
|
**
|
|
** DOS: DNS Client Interface
|
|
**
|
|
** $ENDOFINFO
|
|
*/
|
|
"use strict";
|
|
var log = 0;
|
|
|
|
var util = Require('util');
|
|
var Io = Require('com/io');
|
|
var Net = Require('dos/network');
|
|
var Std = Require('dos/std');
|
|
var Sch = Require('dos/scheduler');
|
|
var Buf = Require('dos/buf');
|
|
var Rpc = Require('dos/rpc');
|
|
var Cs = Require('dos/capset');
|
|
var Comp = Require('com/compat');
|
|
var String = Comp.string;
|
|
var Filename = Comp.filename;
|
|
var Array = Comp.array;
|
|
var Perv = Comp.pervasives;
|
|
var Rand = Comp.random;
|
|
var Status = Net.Status;
|
|
var Command = Net.Command;
|
|
var Rights = Net.Rights;
|
|
|
|
|
|
/*
|
|
** Use the default DNS server
|
|
*/
|
|
var DNS_DEFAULT = undefined;
|
|
var DNS_MAXPATH = 255;
|
|
var DNS_DEFAULT_COLS = ['owner','group','others'];
|
|
var DNS_DEFAULT_RIGHTS = [
|
|
Rights.DNS_RGT_OWNER|Rights.DNS_RGT_GROUP|Rights.DNS_RGT_OTHERS|
|
|
Rights.DNS_RGT_READ|Rights.DNS_RGT_MODIFY|Rights.DNS_RGT_DELETE|Rights.DNS_RGT_CREATE,
|
|
Rights.DNS_RGT_GROUP|Rights.DNS_RGT_OTHERS|
|
|
Rights.DNS_RGT_READ,
|
|
Rights.DNS_RGT_OTHERS|
|
|
Rights.DNS_RGT_READ
|
|
];
|
|
var DNS_NTRY = 3;
|
|
var DNS_NOMOREROWS = -1;
|
|
var DNS_MAXCOLUMNS = Net.DNS_MAXCOLUMNS;
|
|
|
|
/** {@link dir_entry~obj}
|
|
* Directory Entry Class - one row
|
|
*
|
|
* @param {string} de_name
|
|
* @param {string} de_time
|
|
* @param {number []} de_columns
|
|
* @constructor
|
|
* @typedef {{de_name,de_time,de_columns}} dir_entry~obj
|
|
*/
|
|
var dir_entry = function (de_name,de_time,de_columns) {
|
|
this.de_name = de_name; // string;
|
|
this.de_time = de_time; // number;
|
|
this.de_columns = de_columns; // rights_bits array;
|
|
};
|
|
|
|
/** {@link dir~obj}
|
|
** Directory Class - One directory
|
|
*
|
|
*
|
|
* @param {capset} [di_capset]
|
|
* @param {number} [di_ncols]
|
|
* @param {number} [di_nrows]
|
|
* @param {string []} [di_colnames]
|
|
* @param {dir_entry []} [di_rows]
|
|
* @param {number} [di_curpos]
|
|
* @constructor
|
|
* @typedef {{di_capset,di_ncols,di_nrows,di_colnames,di_rows,di_curpos}} dir~obj
|
|
*/
|
|
var dir = function (di_capset,di_ncols,di_nrows,di_colnames,di_rows,di_curpos) {
|
|
this.di_capset = di_capset; // capset
|
|
this.di_ncols = di_ncols||0; // int
|
|
this.di_nrows = di_nrows||0; // int
|
|
this.di_colnames = di_colnames||[]; // string array
|
|
this.di_rows = di_rows||[]; // dns_dir_entry array
|
|
this.di_curpos = di_curpos||0; // int
|
|
};
|
|
|
|
/** Directory Entry Object
|
|
*
|
|
* @param de_name
|
|
* @param de_time
|
|
* @param de_columns
|
|
* @returns {dir_entry}
|
|
* @constructor
|
|
*/
|
|
function Dir_entry (de_name,de_time,de_columns) {
|
|
var obj = new dir_entry(de_name,de_time,de_columns);
|
|
Object.preventExtensions(obj);
|
|
return obj;
|
|
}
|
|
/**
|
|
** One directory
|
|
*
|
|
*
|
|
* @param {capset} [di_capset]
|
|
* @param {number} [di_ncols]
|
|
* @param {number} [di_nrows]
|
|
* @param {string []} [di_colnames]
|
|
* @param {dir_entry []} [di_rows]
|
|
* @param {number} [di_curpos]
|
|
* @returns {dir}
|
|
*/
|
|
function Dir (di_capset,di_ncols,di_nrows,di_colnames,di_rows,di_curpos) {
|
|
var obj = new dir(di_capset,di_ncols,di_nrows,di_colnames,di_rows,di_curpos);
|
|
Object.preventExtensions(obj);
|
|
return obj;
|
|
}
|
|
|
|
|
|
/*
|
|
** BUFFER operations
|
|
*/
|
|
function buf_put_rights (buf,rights) {
|
|
Buf.buf_put_int32(buf,rights);
|
|
}
|
|
|
|
function buf_get_rights (buf) {
|
|
var rights=0;
|
|
rights=Buf.buf_get_int32(buf);
|
|
return rights;
|
|
}
|
|
|
|
|
|
/*
|
|
** ==========
|
|
** DNS CLIENT
|
|
* ==========
|
|
*/
|
|
/** {@link dns~obj}
|
|
* DNS Client Programming Interface
|
|
* @param {rpcint} rpc
|
|
* @constructor
|
|
*/
|
|
var dnsint = function(rpc,env) {
|
|
this.rpc=rpc;
|
|
this.std=Std.StdInt(rpc);
|
|
this.cs=Cs.CsInt(rpc);
|
|
this.env=env||{};
|
|
if (!this.env.rootdir) this.env.rootdir=Cs.nilcapset;
|
|
if (!this.env.rootdir) this.env.workdir=Cs.nilcapset;
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @returns {[]}
|
|
*/
|
|
dnsint.prototype.default_colmask = function () {
|
|
var nmasks = Net.DNS_MAXCOLUMNS;
|
|
var def_mask = Io.getenv('DNSMASK','');
|
|
var mask_array=[];
|
|
if (String.equal(def_mask,'')) {
|
|
mask_array=Array.create(nmasks,0xff)
|
|
} else {
|
|
var def_mask_list = def_mask.split(':');
|
|
var def_mask_len = def_mask_list.length;
|
|
if (def_mask_len > nmasks) Io.err('default_colmask: invalid dns mask from environment');
|
|
for (var i=0;i<def_mask_len;i++) {
|
|
mask_array.push(Perv.int_of_string(def_mask_list[i]));
|
|
}
|
|
}
|
|
return mask_array;
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @returns {capset|undefined}
|
|
*/
|
|
dnsint.prototype.get_workdir = function () {
|
|
return this.env.workdir;
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @returns {capset|undefined}
|
|
*/
|
|
dnsint.prototype.get_rootdir = function () {
|
|
return this.env.rootdir;
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @param cap
|
|
*/
|
|
dnsint.prototype.set_workdir = function (cap) {
|
|
this.env.workdir=this.cs.cs_singleton(cap);
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @param cap
|
|
*/
|
|
dnsint.prototype.set_rootdir = function (cap) {
|
|
this.env.rootdir=this.cs.cs_singleton(cap);
|
|
};
|
|
|
|
/**
|
|
** Perform a request to the DNS server. This function tries
|
|
** to find out a valid capability from the capability set 'cs'.
|
|
*
|
|
*
|
|
* @param ntries
|
|
* @param {rpcio} rpcio
|
|
* @param {capset} cs
|
|
*/
|
|
dnsint.prototype.mktrans = function (ntries,rpcio,cs) {
|
|
var cs=cs,
|
|
buf,
|
|
self=this,
|
|
err = Status.STD_UNKNOWN,
|
|
failed = Status.STD_UNKNOWN,
|
|
tries = 1,
|
|
i=0,
|
|
s;
|
|
|
|
if (ntries>1) {
|
|
buf=Buf.Buffer(); // we must save the rpcio data, it may be overridden by a previous transaction!
|
|
Buf.buf_copy(buf,rpcio);
|
|
}
|
|
Io.log((log<1)||('Dns.mktrans max('+ntries+') '+Cs.Print.capset(cs)));
|
|
Sch.ScheduleLoop(function () {
|
|
return (tries <= ntries && err != Net.Status.STD_OK);
|
|
},[
|
|
function () {
|
|
s = cs.cs_suite[i];
|
|
i++;
|
|
if (i==cs.cs_final) {
|
|
i=0; tries++;
|
|
}
|
|
if (s.s_current == true) {
|
|
rpcio.header.h_port = s.s_object.cap_port;
|
|
Net.Copy.private(s.s_object.cap_priv,rpcio.header.h_priv);
|
|
if (ntries>1) Buf.buf_copy(rpcio,buf);
|
|
|
|
Io.log((log<1)||('Dns.mktrans ('+(tries-1)+') '+Rpc.Print.rpcio(rpcio)));
|
|
Sch.ScheduleBlock([
|
|
/*
|
|
** Do the real transaction
|
|
*/
|
|
[Sch.Bind(self.rpc, self.rpc.trans), rpcio],
|
|
[function () {
|
|
Io.log((log<10)||('mktrans returned ' + Rpc.Print.rpcio(rpcio)));
|
|
err = rpcio.status||rpcio.header.h_status;
|
|
if (err==Status.RPC_FAILURE && ntries > 1) {
|
|
/*
|
|
** Retry idempotent operation, but return RPC_FAILURE
|
|
** in case we don't succeed in a following iteration.
|
|
*/
|
|
failed=Status.RPC_FAILURE;
|
|
}
|
|
}]
|
|
]);
|
|
}
|
|
}
|
|
],[
|
|
function () {if (failed!=Status.STD_UNKNOWN) rpcio.status=failed;}
|
|
], function(e) {
|
|
if (typeof e == 'number') rpcio.status=e; else {
|
|
Io.printstack(e,'Dns.mktrans');
|
|
rpcio.status=Status.STD_SYSERR;
|
|
}
|
|
})
|
|
};
|
|
|
|
/**
|
|
** lookup returns the capability-set stored under the name
|
|
** 'path' relative to the directory 'root'. The root directory
|
|
** can be any directory in the directory tree. The path rest
|
|
** that can not be eresolved will be returned, too.
|
|
*
|
|
*
|
|
* @param {capset} rootcs
|
|
* @param {string} path
|
|
* @param {function(status:(Status.STD_OK|*),cs:(capset|undefined),string)} callback
|
|
*/
|
|
dnsint.prototype.dns_lookup = function (rootcs,path,callback) {
|
|
var self=this,
|
|
err,cs,res,
|
|
rpcio,depth,pos,path_len,cs_parent,finished,max_steps;
|
|
Io.log((log<1)||('Dns.dns_lookup ('+path+') root='+(rootcs?Cs.Print.capset(rootcs):'[]')));
|
|
try {
|
|
if (String.equal(path, '/')) {
|
|
rootcs=rootcs||this.get_rootdir();
|
|
if (rootcs) callback(Status.STD_OK, rootcs, '');
|
|
else throw Status.STD_NOTNOW;
|
|
} else {
|
|
path = Filename.path_normalize(path);
|
|
if (path.length==0) throw Status.STD_ARGBAD;
|
|
max_steps=10;
|
|
if (rootcs==DNS_DEFAULT) {
|
|
if (String.get(path,0)=='/') cs=self.get_rootdir();
|
|
else cs=self.get_workdir();
|
|
if (cs==undefined) res=[Status.STD_STD_NOTNOW];
|
|
else res=[Status.STD_OK,cs];
|
|
} else res=[Status.STD_OK,self.cs.cs_copy(rootcs)];
|
|
err=res[0];
|
|
cs=res[1];
|
|
if (err != Status.STD_OK) throw (err==undefined?Status.STD_SYSERR:err);
|
|
/*
|
|
** Loop over the path components step by step and resolve the path.
|
|
** Each run, the next path component is the new parent directory
|
|
** for the next lookup.
|
|
*/
|
|
rpcio=self.rpc.router.pkt_get();
|
|
depth= 1;
|
|
pos;
|
|
path_len=path.length;
|
|
cs_parent=cs;
|
|
finished=false;
|
|
if (path_len>0 && String.get(path,0)=='/') {
|
|
// remove a leading slash from path
|
|
path=String.trim(path,1,0);
|
|
}
|
|
Sch.ScheduleLoop(function () {
|
|
return (finished==false && err==Status.STD_OK);
|
|
},[
|
|
function () {
|
|
if (depth>max_steps) {finished=true; cs=undefined; err=Status.STD_OVERFLOW;}
|
|
path_len=path.length;
|
|
if (String.equal(path,'.') || path_len==0) {
|
|
finished=true;
|
|
cs=cs_parent;
|
|
}
|
|
},
|
|
function () {
|
|
if (!finished && err==Status.STD_OK) {
|
|
rpcio.header.h_command=Command.DNS_LOOKUP;
|
|
rpcio.header.h_status=Status.STD_UNKNOWN;
|
|
rpcio.pos=0;
|
|
Buf.buf_put_string(rpcio,path);
|
|
/*
|
|
* ------------
|
|
* name(string)
|
|
* ------------
|
|
* path(string)
|
|
* cs(capset)
|
|
* ------------
|
|
*/
|
|
self.mktrans(DNS_NTRY,rpcio,cs_parent);
|
|
}
|
|
},
|
|
function () {
|
|
if (!finished && err==Status.STD_OK) {
|
|
err=rpcio.status||rpcio.header.h_status;
|
|
if (err==Status.STD_OK) {
|
|
// Get path
|
|
rpcio.pos=0;
|
|
path=Buf.buf_get_string(rpcio);
|
|
// Get capset
|
|
cs=Cs.buf_get_capset(rpcio);
|
|
cs_parent=cs;
|
|
// Remove a leading slash from path
|
|
if (path.length>0 && path[0]=='/') path=String.trim(path,1,0);
|
|
depth++;
|
|
} else {
|
|
finished=true;
|
|
cs=undefined;
|
|
}
|
|
}
|
|
}
|
|
],[
|
|
// Finalize block
|
|
function () {
|
|
callback(err,cs,path);
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
}
|
|
], // Exception handler function
|
|
function(e) {
|
|
if (typeof e == 'number') callback(e, undefined, '');
|
|
else {
|
|
Io.printstack(e,'Dns.dns_lookup');
|
|
callback(Status.STD_SYSERR, undefined, '');
|
|
}
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
}
|
|
);
|
|
}
|
|
} catch (e) {
|
|
if (typeof e == 'number') callback(e, undefined, ''); else {
|
|
Io.printstack(e,'Dns.dns_lookup');
|
|
callback(Status.STD_SYSERR, undefined, '');
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
** Lookup a set of directory capabilities specified by a (directory capability set - row name) list.
|
|
** The (status, row capset) tuple list is returned.
|
|
*
|
|
* @param {capset} server root directory
|
|
* @param {* []} dirs (dir:capset * rowname:string) []
|
|
* @param {function((Status.STD_OK|*),* [])} callback (Status*capset) []
|
|
*/
|
|
dnsint.prototype.dns_setlookup = function (server,dirs,callback) {
|
|
var rpcio=self.rpc.router.pkt_get();
|
|
var ndirs = dirs.length;
|
|
var stat;
|
|
Sch.ScheduleBlock([
|
|
function () {
|
|
/*
|
|
* ------------
|
|
* nrows(int16)
|
|
* [
|
|
* dir(capset)
|
|
* rowname(string)
|
|
* ] #nrows
|
|
* ------------
|
|
* [
|
|
* status(int16)
|
|
* cs(capset)
|
|
* ] #nrows
|
|
* ------------
|
|
*/
|
|
rpcio.header.h_command=Command.DNS_SETLOOKUP;
|
|
rpcio.header.h_status=Status.STD_UNKNOWN;
|
|
rpcio.pos=0;
|
|
Buf.buf_put_int16(dirs.length);
|
|
Array.iter (dirs,function(dir) {
|
|
Cs.buf_put_capset(rpcio,dir[0]); // directory capability set
|
|
Buf.buf_put_string(rpcio,dir[1]); // row name
|
|
});
|
|
self.mktrans(DNS_NTRY,rpcio,server);
|
|
},
|
|
function(){
|
|
var i;
|
|
var res;
|
|
if (rpcio.status==Status.STD_OK) stat=rpcio.header.h_status;
|
|
if (stat != Status.STD_OK) throw(stat);
|
|
rpcio.pos=0;
|
|
for(i=0;i<ndirs;i++) {
|
|
var statn=Buf.buf_get_int16(rpcio);
|
|
var cs=Cs.buf_get_capset(rpcio);
|
|
res.push([stat,cs]);
|
|
}
|
|
callback(stat,res);
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
}
|
|
],function(e) {
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
if (typeof e == 'number') callback(e, []); else {
|
|
Io.printstack(e,'Dns.dns_setlookup');
|
|
callback(Status.STD_SYSERR,[]);
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
** dns_list: return the row list of the directory specified by
|
|
** 'dir'
|
|
*
|
|
*
|
|
* @param {capset} dircs
|
|
* @param {function((Status.STD_OK|*),dir|undefined)} callback
|
|
*/
|
|
dnsint.prototype.dns_list = function (dircs,callback) {
|
|
var self=this,
|
|
stat=Status.STD_OK,
|
|
dir=Dir(dircs),
|
|
next_row=0,
|
|
ncols=0,
|
|
nrows=0,
|
|
rowoff=0,
|
|
rpcio=this.rpc.router.pkt_get();
|
|
|
|
function addtodir(firstrow,numrows,buf) {
|
|
var i,j;
|
|
|
|
for (i = firstrow; i < numrows; i++) {
|
|
var name = Buf.buf_get_string(buf);
|
|
var time = Buf.buf_get_int32(buf);
|
|
var rbits = [];
|
|
for (j = 0; j < dir.di_ncols; j++) {
|
|
rbits[j] = buf_get_rights(buf);
|
|
}
|
|
dir.di_rows.push(Dir_entry(name, time, rbits));
|
|
}
|
|
}
|
|
Io.log((log<1)||('Dns.dns_list dircs='+Cs.Print.capset(dircs)));
|
|
Sch.ScheduleLoop(
|
|
function (index) {
|
|
return (stat==Status.STD_OK && next_row != DNS_NOMOREROWS);
|
|
},[
|
|
function () {
|
|
rpcio.header.h_command = Command.DNS_LIST;
|
|
rpcio.header.h_status = Status.STD_UNKNOWN;
|
|
rpcio.pos = 0;
|
|
Buf.buf_put_int16(rpcio,rowoff);
|
|
/*
|
|
* --------------
|
|
* rowoff(int16)
|
|
* ---------------
|
|
* next_row(int16)
|
|
* ncols(int16)
|
|
* nrows(int16)
|
|
* cols: [name(string)] #ncols
|
|
* rows: [
|
|
* name(string)
|
|
* time(int32)
|
|
* [rights(int16)] #ncols
|
|
* ] #nrows
|
|
* --------------
|
|
*/
|
|
self.mktrans(DNS_NTRY, rpcio, dircs);
|
|
},
|
|
function () {
|
|
var i,rowoff,nrowschunk,numrows;
|
|
rpcio.pos=0;
|
|
|
|
if (rpcio.status==Status.STD_OK) stat=rpcio.header.h_status;
|
|
else stat=rpcio.status;
|
|
if (stat==Status.STD_OK) {
|
|
if (next_row==0) {
|
|
/*
|
|
** Initial request...
|
|
*/
|
|
next_row = Buf.buf_get_int16(rpcio);
|
|
ncols = Buf.buf_get_int16(rpcio);
|
|
nrows = Buf.buf_get_int16(rpcio);
|
|
dir.di_ncols=ncols;
|
|
dir.di_nrows=nrows;
|
|
for (i=0;i<ncols;i++) {
|
|
dir.di_colnames.push(Buf.buf_get_string(rpcio));
|
|
}
|
|
if (nrows>0) {
|
|
if (next_row != DNS_NOMOREROWS) numrows = next_row;
|
|
else numrows=nrows;
|
|
addtodir(0,numrows,rpcio);
|
|
}
|
|
} else {
|
|
/*
|
|
** following requests
|
|
*/
|
|
next_row = Buf.buf_get_int16(rpcio);
|
|
ncols = Buf.buf_get_int16(rpcio);
|
|
nrowschunk = Buf.buf_get_int16(rpcio);
|
|
for (i=0;i<ncols;i++) {
|
|
Buf.buf_get_string(rpcio);
|
|
}
|
|
/*
|
|
** append the current chunk of rows to dirs
|
|
*/
|
|
if (next_row > 0) numrows = next_row-rowoff;
|
|
else numrows=nrowschunk-rowoff;
|
|
addtodir(rowoff,numrows,rpcio);
|
|
}
|
|
}
|
|
}
|
|
],[
|
|
function () {
|
|
callback(stat,dir);
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
}
|
|
],
|
|
function (e) {
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
if (typeof e == 'number') callback(e, undefined); else {
|
|
Io.printstack(e,'Dns.dns_list');
|
|
callback(Status.STD_SYSERR,undefined);
|
|
}
|
|
}
|
|
);
|
|
};
|
|
|
|
/**
|
|
** Append new 'obj' capability to directory specified with capset 'dir'
|
|
** with row 'name' and the new column rights 'cols'. 'name' may not
|
|
** a path! Use dns_lookup to resolve directory capability instead!
|
|
*
|
|
*
|
|
* @param {capset} dir
|
|
* @param {string} name
|
|
* @param {capset} obj
|
|
* @param {number []} cols
|
|
* @param {function(stat:(Status.STD_OK|*))} callback
|
|
*/
|
|
dnsint.prototype.dns_append = function (dir,name,obj,cols,callback) {
|
|
var self=this;
|
|
var ncols=cols.length;
|
|
var rpcio=self.rpc.router.pkt_get();
|
|
var stat=Status.STD_UNKNOWN;
|
|
Sch.ScheduleBlock([
|
|
function() {
|
|
rpcio.header.h_command=Command.DNS_APPEND;
|
|
rpcio.header.h_status=Status.STD_UNKNOWN;
|
|
rpcio.pos=0;
|
|
/*
|
|
* -----
|
|
* name:string
|
|
* obj:capset
|
|
* ncols:number
|
|
* -----
|
|
* -----
|
|
*/
|
|
Buf.buf_put_string(rpcio,name);
|
|
Cs.buf_put_capset(rpcio,obj);
|
|
Buf.buf_put_int16(rpcio,ncols);
|
|
for (var n = 0; n < ncols; n++) {
|
|
buf_put_rights(rpcio, cols[n]);
|
|
}
|
|
self.mktrans(1,rpcio,dir);
|
|
},
|
|
function() {
|
|
if (rpcio.stat && rpcio.stat != Status.STD_OK) stat=rpcio.stat;
|
|
else stat=rpcio.header.h_status;
|
|
callback(stat);
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
}
|
|
],function (e) {
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
if (typeof e == 'number') callback(e); else {
|
|
Io.printstack(e,'Dns.dns_append');
|
|
callback(Status.STD_SYSERR);
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @param {capset} dir
|
|
* @param {string} oldname
|
|
* @param {string} newname
|
|
* @param {function((Status.STD_OK|*))} callback
|
|
*/
|
|
dnsint.prototype.dns_rename = function (dir,oldname,newname,callback) {
|
|
var self=this;
|
|
var stat;
|
|
var rpcio=self.rpc.router.pkt_get();
|
|
Sch.ScheduleBlock([
|
|
function() {
|
|
rpcio.header.h_command=Command.DNS_RENAME;
|
|
rpcio.header.h_status=Status.STD_UNKNOWN;
|
|
rpcio.pos=0;
|
|
/*
|
|
* -----
|
|
* oldname:string
|
|
* newname:string
|
|
* -----
|
|
* -----
|
|
*/
|
|
Buf.buf_put_string(rpcio,oldname);
|
|
Buf.buf_put_string(rpcio,newname);
|
|
self.mktrans(DNS_NTRY,rpcio,dir);
|
|
},
|
|
function() {
|
|
if (rpcio.stat && rpcio.stat != Status.STD_OK) stat=rpcio.stat;
|
|
else stat=rpcio.header.h_status;
|
|
callback(stat);
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
}
|
|
],function (e) {
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
if (typeof e == 'number') callback(e); else {
|
|
Io.printstack(e,'Dns.dns_rename');
|
|
callback(Status.STD_SYSERR);
|
|
}
|
|
});
|
|
|
|
};
|
|
|
|
/**
|
|
** dns_delete deletes the directory entry (which may itself be a
|
|
** directory capability) specified by 'name' in directory
|
|
** specified with capset 'dir'.
|
|
*
|
|
* @param {capset} dir
|
|
* @param {string} name
|
|
* @param {function((Status.STD_OK|*))} callback
|
|
*/
|
|
dnsint.prototype.dns_delete = function (dir,name,callback) {
|
|
var self=this;
|
|
var stat;
|
|
var rpcio=self.rpc.router.pkt_get();
|
|
Sch.ScheduleBlock([
|
|
function() {
|
|
rpcio.header.h_command=Command.DNS_DELETE;
|
|
rpcio.header.h_status=Status.STD_UNKNOWN;
|
|
rpcio.pos=0;
|
|
/*
|
|
* -----
|
|
* rowname:string
|
|
* -----
|
|
* -----
|
|
*/
|
|
Buf.buf_put_string(rpcio,name);
|
|
self.mktrans(1,rpcio,dir);
|
|
},
|
|
function() {
|
|
if (rpcio.stat && rpcio.stat != Status.STD_OK) stat=rpcio.stat;
|
|
else stat=rpcio.header.h_status;
|
|
callback(stat);
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
}
|
|
],function (e) {
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
if (typeof e == 'number') callback(e); else {
|
|
Io.printstack(e,'Dns.dns_delete');
|
|
callback(Status.STD_SYSERR);
|
|
}
|
|
});
|
|
|
|
};
|
|
/**
|
|
*
|
|
* @param {capset} rootdir
|
|
* @param {number []} colnames
|
|
* @param {function((Status.STD_OK|*),capset|undefined)} callback
|
|
*/
|
|
dnsint.prototype.dns_create = function (rootdir,colnames,callback) {
|
|
var cs=undefined;
|
|
var self=this;
|
|
var stat;
|
|
var ncols=colnames.length;
|
|
var rpcio=self.rpc.router.pkt_get();
|
|
Sch.ScheduleBlock([
|
|
function() {
|
|
rpcio.header.h_command=Command.DNS_CREATE;
|
|
rpcio.header.h_status=Status.STD_UNKNOWN;
|
|
rpcio.pos=0;
|
|
/*
|
|
* -----
|
|
* ncols(int16)
|
|
* [colname(string)] #ncols
|
|
* -----
|
|
* cs(capset)
|
|
* -----
|
|
*/
|
|
Buf.buf_put_int16(rpcio,ncols);
|
|
for(var i=0;i<ncols;i++) {
|
|
Buf.buf_put_string(rpcio,colnames[i]);
|
|
}
|
|
self.mktrans(1,rpcio,rootdir);
|
|
},
|
|
function() {
|
|
rpcio.pos=0;
|
|
if (rpcio.stat && rpcio.stat != Status.STD_OK) stat=rpcio.stat;
|
|
else stat=rpcio.header.h_status;
|
|
if (stat==Status.STD_OK) {
|
|
var cs=Cs.buf_get_capset(rpcio);
|
|
callback(stat,cs);
|
|
} else
|
|
callback(stat,undefined);
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
}
|
|
],function (e) {
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
if (typeof e == 'number') callback(e,undefined); else {
|
|
Io.printstack(e,'Dns.dns_create');
|
|
callback(Status.STD_SYSERR,undefined);
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
** dns_destroy deletes the entire directory
|
|
** specified with capset 'dir'.
|
|
*
|
|
* @param {capset} dir
|
|
* @param {string} name
|
|
* @param {function((Status.STD_OK|*))} callback
|
|
*/
|
|
dnsint.prototype.dns_destroy = function (dir,name,callback) {
|
|
var self=this;
|
|
var stat;
|
|
var rpcio=self.rpc.router.pkt_get();
|
|
Sch.ScheduleBlock([
|
|
function() {
|
|
rpcio.header.h_command=Command.STD_DESTROY;
|
|
rpcio.header.h_status=Status.STD_UNKNOWN;
|
|
rpcio.pos=0;
|
|
/*
|
|
* -----
|
|
* -----
|
|
* -----
|
|
*/
|
|
self.mktrans(1,rpcio,dir);
|
|
},
|
|
function() {
|
|
if (rpcio.stat && rpcio.stat != Status.STD_OK) stat=rpcio.stat;
|
|
else stat=rpcio.header.h_status;
|
|
callback(stat);
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
}
|
|
],function (e) {
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
if (typeof e == 'number') callback(e); else {
|
|
Io.printstack(e,'Dns.dns_destroy');
|
|
callback(Status.STD_SYSERR);
|
|
}
|
|
});
|
|
|
|
};
|
|
|
|
/** Try to get the server root capability set (e.g., from host server),
|
|
* Only the host server port is required without any authorization fields.
|
|
* Therefore, the request can be rejected by a server.
|
|
*
|
|
* @param {port} server
|
|
* @param {function((Status.STD_OK|*),capability|undefined)} callback
|
|
*/
|
|
dnsint.prototype.dns_getrootcap = function (server,callback) {
|
|
var cs=undefined;
|
|
var self=this;
|
|
var stat;
|
|
var rpcio=self.rpc.router.pkt_get();
|
|
Sch.ScheduleBlock([
|
|
function() {
|
|
rpcio.header.h_port=server;
|
|
rpcio.header.h_priv=Net.Private();
|
|
rpcio.header.h_command=Command.DNS_GETROOT;
|
|
rpcio.header.h_status=Status.STD_UNKNOWN;
|
|
rpcio.pos=0;
|
|
/*
|
|
* -----
|
|
* -----
|
|
* cap(capability)
|
|
* -----
|
|
*/
|
|
/*
|
|
** Do the real transaction
|
|
*/
|
|
self.rpc.trans(rpcio);
|
|
},
|
|
function() {
|
|
rpcio.pos=0;
|
|
if (rpcio.stat && rpcio.stat != Status.STD_OK) stat=rpcio.stat;
|
|
else stat=rpcio.header.h_status;
|
|
if (stat==Status.STD_OK) {
|
|
var cap=Buf.buf_get_cap(rpcio);
|
|
callback(stat,cap);
|
|
} else
|
|
callback(stat,undefined);
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
}
|
|
],function (e) {
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
if (typeof e == 'number') callback(e,undefined); else {
|
|
Io.printstack(e,'Dns.dns_getrootcap');
|
|
callback(Status.STD_SYSERR,undefined);
|
|
}
|
|
});
|
|
};
|
|
|
|
/** Try to get the default AFS server capability set (e.g., from DNS server),
|
|
*
|
|
* @param {capset} rootdir
|
|
* @param {function((Status.STD_OK|*),capability|undefined)} callback
|
|
*/
|
|
dnsint.prototype.dns_getdefafs = function (rootdir,callback) {
|
|
var cs=undefined;
|
|
var self=this;
|
|
var stat;
|
|
var rpcio=self.rpc.router.pkt_get();
|
|
Sch.ScheduleBlock([
|
|
function() {
|
|
rpcio.header.h_command=Command.DNS_GETDEFAFS;
|
|
rpcio.header.h_status=Status.STD_UNKNOWN;
|
|
rpcio.pos=0;
|
|
/*
|
|
* -----
|
|
* -----
|
|
* cap(capability)
|
|
* -----
|
|
*/
|
|
self.mktrans(1,rpcio,rootdir);
|
|
},
|
|
function() {
|
|
rpcio.pos=0;
|
|
if (rpcio.stat && rpcio.stat != Status.STD_OK) stat=rpcio.stat;
|
|
else stat=rpcio.header.h_status;
|
|
if (stat==Status.STD_OK) {
|
|
var cap=Buf.buf_get_cap(rpcio);
|
|
callback(stat,cap);
|
|
} else
|
|
callback(stat,undefined);
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
}
|
|
],function (e) {
|
|
self.rpc.router.pkt_discard(rpcio);
|
|
if (typeof e == 'number') callback(e,undefined); else {
|
|
Io.printstack(e,'Dns.dns_getdefafs');
|
|
callback(Status.STD_SYSERR,undefined);
|
|
}
|
|
});
|
|
};
|
|
|
|
/** DNS Client Interface
|
|
*
|
|
*
|
|
*/
|
|
module.exports = {
|
|
DNS_MAXPATH:DNS_MAXPATH,
|
|
DNS_DEFAULT_COLS:DNS_DEFAULT_COLS,
|
|
DNS_DEFAULT_RIGHTS:DNS_DEFAULT_RIGHTS,
|
|
DNS_MAXCOLUMNS:DNS_MAXCOLUMNS,
|
|
DNS_NOMOREROWS:DNS_NOMOREROWS,
|
|
buf_put_rights:buf_put_rights,
|
|
buf_get_rights:buf_get_rights,
|
|
RIGHTS_SIZE:4,
|
|
Dir_entry:Dir_entry,
|
|
Dir:Dir,
|
|
/**
|
|
*
|
|
* @param {rpcint} rpc
|
|
* @returns {dnsint}
|
|
*/
|
|
DnsInt: function(rpc,env) {
|
|
var obj = new dnsint(rpc,env);
|
|
Object.preventExtensions(obj);
|
|
return obj;
|
|
}
|
|
};
|