Merge pull request #1197 from urbit/ccr-fast-boot

cc-release: flexible boot sequence, fast-boot support
This commit is contained in:
Joe Bryan 2019-03-29 16:21:37 -07:00 committed by GitHub
commit 2f9d65ecd2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 849 additions and 371 deletions

View File

@ -0,0 +1 @@
6d6ec85d6aa9200d366d0998326726ef1965d092

View File

@ -2,6 +2,10 @@
set -euo pipefail
set -x
if [ ! -f ./pin-arvo-commit.txt ]; then
exit 0
fi
if [ ! -f ./pin-brass-pill.txt ]; then
echo "missing .travis/pin-brass-pill.txt"
exit 1

View File

@ -6,7 +6,22 @@ var Urbit = runner.Urbit;
var ERROR = runner.ERROR;
var actions = runner.actions
var args = ['-cgSF', 'zod', '-B', 'brass.pill', 'zod'];
var args =
(function() {
var commit;
try {
commit = fs.readFileSync('./pin-arvo-commit.txt', 'utf-8');
}
catch (e) {
return ['-cgSF', 'zod', '-B', 'brass.pill', 'zod'];
}
var hash = commit.slice(0, 10);
var pill = 'https://bootstrap.urbit.org/git-' + hash + '.pill';
return ['-u', pill, '-cgPSF', 'zod', 'zod'];
})();
var urbit = new Urbit(args);
// vere hangs (always?) with run in travis-ci with -P

View File

@ -546,8 +546,7 @@
/* u3_opts: command line configuration.
*/
typedef struct _u3_opts {
// XX find a way to re-enable -A (fastboot)
// c3_c* arv_c; // -A, initial sync from
c3_c* arv_c; // -A, initial sync from
c3_o abo; // -a, abort aggressively
c3_c* pil_c; // -B, bootstrap from
c3_o bat; // -b, batch create
@ -573,8 +572,7 @@
c3_o qui; // -q, quiet
c3_o rep; // -R, report build info
c3_o has; // -S, Skip battery hashes
// XX find a way to re-enable -s (auto-pill)
// c3_o git; // -s, pill url from arvo git hash
c3_o git; // -s, pill url from arvo git hash
c3_o etn; // -t, trust snapshot for pre-boot
c3_c* url_c; // -u, pill url
c3_o vno; // -V, replay without reboots
@ -666,10 +664,10 @@
*/
typedef struct _u3_pier {
c3_c* pax_c; // pier directory
c3_c* sys_c; // pill file
c3_w wag_w; // config flags
c3_d gen_d; // last event discovered
c3_d but_d; // boot barrier
c3_d lif_d; // lifecycle boot barrier
c3_d tic_d[1]; // ticket (unstretched)
c3_d sec_d[1]; // generator (unstretched)
c3_d key_d[4]; // secret (stretched)
@ -678,6 +676,7 @@
c3_s por_s; // UDP port
c3_o fak_o; // yes iff fake security
u3_noun bot; // boot event XX review
u3_noun pil; // pill XX review
u3_disk* log_u; // event log
u3_lord* god_u; // computer
u3_ames* sam_u; // packet interface
@ -1073,10 +1072,10 @@
void
u3_unix_ef_move(void);
/* u3_unix_initial_into(): intialize filesystem from urb/zod
/* u3_unix_initial_into_card(): create initial filesystem sync card.
*/
void
u3_unix_ef_initial_into(u3_pier *pir_u);
u3_noun
u3_unix_initial_into_card(c3_c* arv_c);
/* u3_unix_ef_look(): update filesystem from unix
*/
@ -1227,7 +1226,7 @@
/* u3_pier_create(): create a pier, loading existing.
*/
u3_pier*
u3_pier_create(c3_w wag_w, c3_c* pax_c, c3_c* sys_c);
u3_pier_create(c3_w wag_w, c3_c* pax_c);
/* u3_pier_interrupt(): interrupt running process.
*/

View File

@ -72,10 +72,7 @@ _main_getopt(c3_i argc, c3_c** argv)
u3_Host.ops_u.dry = c3n;
u3_Host.ops_u.etn = c3n;
u3_Host.ops_u.gab = c3n;
// XX find a way to re-enable -s (auto-pill)
//
// u3_Host.ops_u.git = c3n;
u3_Host.ops_u.git = c3n;
// always disable hashboard
// XX temporary, remove once hashes are added
@ -92,10 +89,8 @@ _main_getopt(c3_i argc, c3_c** argv)
u3_Host.ops_u.veb = c3n;
u3_Host.ops_u.kno_w = DefaultKernel;
// XX re-enable -s, -A
//
while ( -1 != (ch_i=getopt(argc, argv,
"G:J:B:K:H:w:u:e:E:f:F:k:m:p:LjabcCdgqtvxPDRS")) )
"G:J:B:K:A:H:w:u:e:E:f:F:k:m:p:LjabcCdgqstvxPDRS")) )
{
switch ( ch_i ) {
case 'J': {
@ -111,10 +106,8 @@ _main_getopt(c3_i argc, c3_c** argv)
break;
}
case 'A': {
// XX find a way to re-enable -A (fastboot)
// u3_Host.ops_u.arv_c = strdup(optarg);
// break;
return c3n;
u3_Host.ops_u.arv_c = strdup(optarg);
break;
}
case 'H': {
u3_Host.ops_u.dns_c = strdup(optarg);
@ -188,8 +181,7 @@ _main_getopt(c3_i argc, c3_c** argv)
case 'D': { u3_Host.ops_u.dry = c3y; break; }
case 'q': { u3_Host.ops_u.qui = c3y; break; }
case 'v': { u3_Host.ops_u.veb = c3y; break; }
// XX find a way to re-enable -s (auto-pill)
// case 's': { u3_Host.ops_u.git = c3y; break; }
case 's': { u3_Host.ops_u.git = c3y; break; }
case 'S': { u3_Host.ops_u.has = c3y; break; }
case 't': { u3_Host.ops_u.etn = c3y; break; }
case '?': default: {
@ -325,20 +317,18 @@ _main_getopt(c3_i argc, c3_c** argv)
return c3n;
}
else if ( u3_Host.ops_u.nuu == c3y
&& u3_Host.ops_u.url_c == 0 ) {
// XX find a way to re-enable -s (auto-pill)
// && u3_Host.ops_u.git == c3n ) {
&& u3_Host.ops_u.url_c == 0
&& u3_Host.ops_u.git == c3n ) {
u3_Host.ops_u.url_c =
"https://bootstrap.urbit.org/urbit-" URBIT_VERSION ".pill";
}
// XX find a way to re-enable -A (fastboot)
// else if ( u3_Host.ops_u.nuu == c3y
// && u3_Host.ops_u.url_c == 0
// && u3_Host.ops_u.arv_c == 0 ) {
else if ( u3_Host.ops_u.nuu == c3y
&& u3_Host.ops_u.url_c == 0
&& u3_Host.ops_u.arv_c == 0 ) {
// fprintf(stderr, "-s only makes sense with -A\n");
// return c3n;
// }
fprintf(stderr, "-s only makes sense with -A\n");
return c3n;
}
if ( u3_Host.ops_u.pil_c != 0 ) {
struct stat s;

View File

@ -25,6 +25,7 @@
#include <vere/vere.h>
typedef struct _u3_serf {
c3_w len_w; // boot sequence length
c3_d evt_d; // last event processed
c3_l mug_l; // hash of state
c3_d key_d[4]; // disk key
@ -74,7 +75,14 @@
:: +writ: from lord to serf
::
+$ writ
$% :: exit immediately
$% :: prepare to boot
::
:: p: identity
:: q: fake?
:: r: number of boot formulas
::
[%boot p=@p q=? r=@]
:: exit immediately
::
:: p: exit code
::
@ -360,34 +368,6 @@ _serf_sure(u3_noun ovo, u3_noun vir, u3_noun cor)
u3z(u3A->roc);
u3A->roc = cor;
// single-home
//
// XX revise when real keys are supported
// XX dispatch on evt_d, wire, or card tag?
//
if ( c3__boot == u3h(u3t(ovo)) ) {
// ovo=[%boot *]
// vir=[[wire %init @p] ~]
// fec=[%init @p]
//
u3_noun fec = u3t(u3h(vir));
c3_assert( c3__init == u3h(fec) );
c3_assert( u3_none == u3A->our );
u3A->our = u3k(u3t(fec));
u3A->fak = ( c3__fake == u3h(u3t(u3t(ovo))) ) ? c3y : c3n;
{
u3_noun nam = u3dc("scot", 'p', u3k(u3A->our));
c3_c* nam_c = u3r_string(nam);
fprintf(stderr, "boot: ship: %s%s\r\n", nam_c,
(c3y == u3A->fak) ? " (fake)" : "");
free(nam_c);
u3z(nam);
}
}
u3_noun sac = u3_nul;
// intercept |mass, observe |reset
@ -436,10 +416,10 @@ _serf_sure(u3_noun ovo, u3_noun vir, u3_noun cor)
u3z(sac); u3z(ovo);
}
/* _serf_poke_live(): apply event.
/* _serf_work_live(): apply event.
*/
static void
_serf_poke_live(c3_d evt_d, // event number
_serf_work_live(c3_d evt_d, // event number
c3_l mug_l, // mug of state
u3_noun job) // event date
{
@ -545,10 +525,10 @@ _serf_boot_fire(u3_noun eve)
return pro;
}
/* _serf_poke_boot(): apply initial-stage event.
/* _serf_work_boot(): apply initial-stage event.
*/
static void
_serf_poke_boot(c3_d evt_d,
_serf_work_boot(c3_d evt_d,
c3_l mug_l,
u3_noun job)
{
@ -559,7 +539,7 @@ _serf_poke_boot(c3_d evt_d,
fprintf(stderr, "serf: (%" PRIu64 ")| boot\r\n", evt_d);
if ( 5 == evt_d ) {
if ( u3V.len_w == evt_d ) {
u3_noun eve, pru;
eve = u3kb_flop(u3A->roe);
@ -596,11 +576,11 @@ _serf_poke_work(c3_d evt_d, // event number
c3_l mug_l, // mug of state
u3_noun job) // full event
{
if ( evt_d < 6 ) {
_serf_poke_boot(evt_d, mug_l, job);
if ( evt_d <= u3V.len_w ) {
_serf_work_boot(evt_d, mug_l, job);
}
else {
_serf_poke_live(evt_d, mug_l, job);
_serf_work_live(evt_d, mug_l, job);
}
}
@ -612,6 +592,18 @@ _serf_poke_exit(c3_w cod_w) // exit code
exit(cod_w);
}
/* _serf_poke_boot(): prepare to boot.
*/
static void
_serf_poke_boot(u3_noun who, u3_noun fak, c3_w len_w)
{
c3_assert( u3_none == u3A->our );
u3A->our = who;
u3A->fak = fak;
u3V.len_w = len_w;
}
/* _serf_poke():
*/
void
@ -628,6 +620,29 @@ _serf_poke(void* vod_p, u3_noun mat)
goto error;
}
case c3__boot: {
u3_noun who, fak, len;
c3_w len_w;
if ( (c3n == u3r_qual(jar, 0, &who, &fak, &len)) ||
(c3n == u3ud(who)) ||
(1 < u3r_met(7, who)) ||
(c3n == u3ud(fak)) ||
(1 < u3r_met(0, fak)) ||
(c3n == u3ud(len)) ||
(1 < u3r_met(3, len)) )
{
goto error;
}
len_w = u3r_word(0, len);
u3k(who);
u3k(fak);
u3z(jar);
return _serf_poke_boot(who, fak, len_w);
}
case c3__work: {
u3_noun evt, mug, job;
c3_d evt_d;
@ -676,7 +691,6 @@ _serf_poke(void* vod_p, u3_noun mat)
goto error;
}
fprintf(stderr, "serf: save\r\n");
u3z(jar);
return u3e_save();
@ -704,11 +718,15 @@ u3_serf_boot(void)
0, // XX u3r_mug(u3A->roc),
u3nc(u3k(u3A->our), u3k(u3A->fak))));
/* disable hashboard for fake ships
*/
// disable hashboard for fake ships
//
if ( c3y == u3A->fak ) {
u3C.wag_w |= u3o_hashless;
}
// no boot sequence expected
//
u3V.len_w = 0;
}
fprintf(stderr, "serf: play %" PRIu64 "\r\n", nex_d);

View File

@ -2,6 +2,7 @@
**
** the main loop of the daemon process
*/
#include <curl/curl.h>
#include <unistd.h>
#include <uv.h>
#include "all.h"
@ -12,39 +13,123 @@
static c3_c sag_w;
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: wyrd: requires auth to a single relevant ship ::
:: doom: requires auth to the daemon itself ::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|% ::
+$ fate :: client to lord
$% [%auth p=(unit ship) q=@] :: authenticate client
[%wyrd p=ship q=wyrd] :: ship action
[%doom p=doom] :: daemon command
== ::
+$ wyrd :: ship action
$% [%susp ~] :: release this pier
[%vent p=ovum] :: generate event
== ::
+$ doom :: daemon command
$% [%boot p=boot q=@pill r=@t] :: boot (r=pier)
[%exit ~] :: end the daemon
[%pier p=(unit @t)] :: acquire a pier
[%root p=ship q=wyrd] :: admin ship actions
== ::
+$ boot :: boot procedures
$% [%come p=(unit ship)] :: mine a comet
[%dawn p=seed] :: real keys
[%fake p=who] :: fake keys
== ::
+$ pill :: boot sequence
(each path=@t pill=@) ::
+$ cede :: lord to client
$% [%cede p=ship q[(list ovum)] :: send cards
[%firm ~] :: accept command
[%deny p=@t] :: reject command
== ::
-- ::
:: king/client protocol:
::
|%
:: +fate: client to lord
::
+$ fate
$% :: authenticate client
::
[%auth p=(unit ship) q=@]
:: ship action
::
[%wyrd p=ship q=wyrd]
:: daemon command
::
[%doom p=doom]
==
:: +wyrd: ship action
::
:: Should require auth to a single relevant ship
::
+$ wyrd
$% :: release this pier
::
:: XX not implemented
::
[%susp ~]
:: generate event
::
:: XX partially implemented
::
[%vent p=ovum]
==
:: +doom: daemon command
::
:: Should require auth to the daemon itself
::
+$ doom
$% :: boot
::
:: p: boot procedure
:: q: pill specifier
:: r: path to pier
::
[%boot p=boot q=pill r=@t]
:: end the daemon
::
:: XX not implemented
::
[%exit ~]
:: acquire a pier
::
:: XX used for restart, may not be right
::
[%pier p=(unit @t)]
:: admin ship actions
::
:: XX not implemented
::
[%root p=ship q=wyrd]
==
:: +boot: boot procedures
::
+$ boot
$% :: mine a comet
::
:: p: optionally under a specific star
::
[%come p=(unit ship)]
:: boot with real keys
::
:: And perform pre-boot validation, retrieve snapshot, etc.
::
[%dawn p=seed]
:: boot with fake keys
::
:: p: identity
::
[%fake p=ship]
==
:: +pill: boot-sequence ingredients
::
+$ pill
%+ each
:: %&: complete pill (either +brass or +solid)
::
:: p: jammed pill
:: q: optional %into ovum overriding that of .p
::
[p=@ q=(unit ovum)]
:: %|: incomplete pill (+ivory)
::
:: XX not implemented, needs generation of
:: %veer ova for install %zuse and the vanes
::
:: p: jammed pill
:: q: module ova
:: r: userspace ova
::
[p=@ q=(list ovum) r=(list ovum)]
:: +cede: lord to client
::
:: XX not implemented
::
+$ cede
$% :: send cards
::
:: XX presumably the effects of %vent in +wyrd
::
[%cede p=ship q=(list ovum)]
:: accept command
::
[%firm ~]
:: reject command
::
[%deny p=@t]
==
--
*/
void _king_auth(u3_noun auth);
@ -333,20 +418,155 @@ _king_socket_connect(uv_stream_t *sock, int status)
u3_newt_read((u3_moat *)mor_u);
}
/* _boothack_pill(): parse CLI pill arguments into (each path pill)
/* _king_curl_alloc(): allocate a response buffer for curl
** XX deduplicate with dawn.c
*/
static size_t
_king_curl_alloc(void* dat_v, size_t uni_t, size_t mem_t, uv_buf_t* buf_u)
{
size_t siz_t = uni_t * mem_t;
buf_u->base = c3_realloc(buf_u->base, 1 + siz_t + buf_u->len);
memcpy(buf_u->base + buf_u->len, dat_v, siz_t);
buf_u->len += siz_t;
buf_u->base[buf_u->len] = 0;
return siz_t;
}
/* _king_get_atom(): HTTP GET url_c, produce the response body as an atom.
** XX deduplicate with dawn.c
*/
static u3_noun
_king_get_atom(c3_c* url_c)
{
CURL *curl;
CURLcode result;
long cod_l;
uv_buf_t buf_u = uv_buf_init(c3_malloc(1), 0);
if ( !(curl = curl_easy_init()) ) {
fprintf(stderr, "failed to initialize libcurl\n");
exit(1);
}
curl_easy_setopt(curl, CURLOPT_URL, url_c);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _king_curl_alloc);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&buf_u);
result = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &cod_l);
// XX retry?
//
if ( CURLE_OK != result ) {
fprintf(stderr, "failed to fetch %s: %s\n",
url_c, curl_easy_strerror(result));
exit(1);
}
if ( 300 <= cod_l ) {
fprintf(stderr, "error fetching %s: HTTP %ld\n", url_c, cod_l);
exit(1);
}
curl_easy_cleanup(curl);
return u3i_bytes(buf_u.len, (const c3_y*)buf_u.base);
}
/* _get_cmd_output(): Run a shell command and capture its output.
Exits with an error if the command fails or produces no output.
The 'out_c' parameter should be an array of sufficient length to hold
the command's output, up to a max of len_c characters.
*/
static void
_get_cmd_output(c3_c *cmd_c, c3_c *out_c, c3_w len_c)
{
FILE *fp = popen(cmd_c, "r");
if ( NULL == fp ) {
fprintf(stderr, "'%s' failed\n", cmd_c);
exit(1);
}
if ( NULL == fgets(out_c, len_c, fp) ) {
fprintf(stderr, "'%s' produced no output\n", cmd_c);
exit(1);
}
pclose(fp);
}
/* _arvo_hash(): get a shortened hash of the last git commit
that modified the sys/ directory in arvo.
hax_c must be an array with length >= 11.
*/
static void
_arvo_hash(c3_c *out_c, c3_c *arv_c)
{
c3_c cmd_c[2048];
sprintf(cmd_c, "git -C %s log -1 HEAD --format=%%H -- sys/", arv_c);
_get_cmd_output(cmd_c, out_c, 11);
out_c[10] = 0; // end with null-byte
}
/* _git_pill_url(): produce a URL from which to download a pill
based on the location of an arvo git repository.
*/
static void
_git_pill_url(c3_c *out_c, c3_c *arv_c)
{
c3_c hax_c[11];
assert(NULL != arv_c);
if ( 0 != system("which git >> /dev/null") ) {
fprintf(stderr, "boot: could not find git executable\r\n");
exit(1);
}
_arvo_hash(hax_c, arv_c);
sprintf(out_c, "https://bootstrap.urbit.org/git-%s.pill", hax_c);
}
/* _boothack_pill(): parse CLI pill arguments into +pill specifier
*/
static u3_noun
_boothack_pill(void)
{
if ( 0 == u3_Host.ops_u.pil_c ) {
// XX download default pill
// XX support -u
//
fprintf(stderr, "boot: new ship must specify pill (-B)\r\n");
exit(1);
u3_noun arv = u3_nul;
u3_noun pil;
if ( 0 != u3_Host.ops_u.pil_c ) {
fprintf(stderr, "boot: loading pill %s\r\n", u3_Host.ops_u.pil_c);
pil = u3m_file(u3_Host.ops_u.pil_c);
}
else {
c3_c url_c[2048];
if ( (c3y == u3_Host.ops_u.git) &&
(0 != u3_Host.ops_u.arv_c) )
{
_git_pill_url(url_c, u3_Host.ops_u.arv_c);
}
else {
c3_assert( 0 != u3_Host.ops_u.url_c );
strcpy(url_c, u3_Host.ops_u.url_c);
}
fprintf(stderr, "boot: downloading pill %s\r\n", url_c);
pil = _king_get_atom(url_c);
}
return u3nc(c3y, u3i_string(u3_Host.ops_u.pil_c));
if ( 0 != u3_Host.ops_u.arv_c ) {
fprintf(stderr, "boot: preparing filesystem from %s\r\n",
u3_Host.ops_u.arv_c);
arv = u3nc(u3_nul, u3_unix_initial_into_card(u3_Host.ops_u.arv_c));
}
return u3nt(c3y, pil, arv);
}
/* _boothack_key(): parse a private key file or value

View File

@ -94,6 +94,53 @@ _pier_work_bail(void* vod_p,
fprintf(stderr, "pier: work error: %s\r\n", err_c);
}
/* _pier_save_boot_complete(): commit complete.
*/
static void
_pier_save_boot_complete(void* vod_p)
{
// no-op, callback required by u3_foil_append()
//
}
/* _pier_save_boot(): save boot metadata.
*/
static void
_pier_save_boot(u3_pier* pir_u, u3_atom mat)
{
// XX deduplicate with _pier_disk_commit_request
//
c3_d len_d = u3r_met(6, mat);
c3_d* buf_d = c3_malloc(8 * len_d);
u3r_chubs(0, len_d, buf_d, mat);
u3_foil_append(_pier_save_boot_complete,
(void*)0,
pir_u->log_u->fol_u,
buf_d,
len_d);
}
/* _pier_work_boot(): prepare serf boot.
*/
static void
_pier_work_boot(u3_pier* pir_u, c3_o sav_o)
{
u3_lord* god_u = pir_u->god_u;
u3_noun who = u3i_chubs(2, pir_u->who_d);
u3_noun len = u3i_chubs(1, &pir_u->lif_d);
u3_noun msg = u3nq(c3__boot, who, pir_u->fak_o, len);
u3_atom mat = u3ke_jam(msg);
if ( c3y == sav_o ) {
_pier_save_boot(pir_u, u3k(mat));
}
u3_newt_write(&god_u->inn_u, mat, 0);
}
/* _pier_disk_shutdown(): close the log.
*/
static void
@ -782,6 +829,39 @@ _pier_disk_load_commit(u3_pier* pir_u,
c3_free(buf_d);
ovo = u3ke_cue(u3k(mat));
// single-home
//
if ( (0ULL == pos_d) &&
(1ULL == lav_d) )
{
u3_noun who, fak, len;
c3_assert( c3__boot == u3h(ovo) );
u3x_qual(ovo, 0, &who, &fak, &len);
c3_assert( c3y == u3ud(who) );
c3_assert( 1 >= u3r_met(7, who) );
c3_assert( c3y == u3ud(fak) );
c3_assert( 1 >= u3r_met(0, fak) );
c3_assert( c3y == u3ud(len) );
c3_assert( 1 >= u3r_met(3, len) );
pir_u->fak_o = (c3_o)fak;
pir_u->lif_d = u3r_word(0, len);
u3r_chubs(0, 2, pir_u->who_d, who);
// Disable networking for fake ships
//
if ( c3y == pir_u->fak_o ) {
u3_Host.ops_u.net = c3n;
}
u3z(mat);
u3z(ovo);
break;
}
c3_assert(c3__work == u3h(ovo));
evt = u3h(u3t(ovo));
job = u3k(u3t(u3t(u3t(ovo))));
@ -846,160 +926,221 @@ _pier_disk_load_commit(u3_pier* pir_u,
}
/* _pier_boot_vent(): create and enqueue boot sequence
**
** per cgy:
** this new boot sequence is almost, but not quite,
** the right thing. see new arvo.
*/
static void
_pier_boot_vent(u3_pier* pir_u)
{
c3_w inx_w = 1;
if ( !u3A->sys ) {
fprintf(stderr, "boot: loading pill %s\r\n", pir_u->sys_c);
u3A->sys = u3m_file(pir_u->sys_c);
}
// bot: boot formulas
// mod: module ova
// use: userpace ova
//
u3_noun bot, mod, use;
// extract boot formulas and module/userspace ova from pill
//
{
u3_noun lal = u3ke_cue(u3k(u3A->sys));
u3_noun pil_p, pil_q, pil_r;
u3_noun pro;
/* this new boot sequence is almost, but not quite,
** the right thing. see new arvo.
*/
{
u3_noun who = u3i_chubs(2, pir_u->who_d);
u3_noun bot, mod, fil;
c3_assert( c3y == u3du(pir_u->pil) );
u3r_trel(lal, &bot, &mod, &fil);
pir_u->but_d = 0;
/* insert boot sequence directly
*/
{
u3_noun seq = u3k(bot);
{
u3_noun all = seq;
pir_u->but_d += u3kb_lent(u3k(all));
while ( all ) {
_pier_insert(pir_u, 0, u3k(u3h(all)));
inx_w++;
all = u3t(all);
}
}
u3z(seq);
}
/* insert module sequence, prepending first identity event
*/
{
u3_noun seq = u3k(mod);
// prepend initial entropy
// XX u3_pier_rand or _pier_zen?
// XX move to _pier_loop_wake?
//
{
c3_w eny_w[16];
u3_noun eny;
c3_rand(eny_w);
eny = u3i_words(16, eny_w);
u3_noun wir = u3nt(u3_blip, c3__arvo, u3_nul);
u3_noun car = u3nc(c3__wack, eny);
u3_noun ovo = u3nc(wir, car);
seq = u3nc(ovo, seq);
}
// prepend identity event to module sequence
// to set single-home
//
{
u3_noun wir = u3nt(u3_blip, c3__arvo, u3_nul);
u3_noun car = u3nc(c3__whom, u3k(who));
u3_noun ovo = u3nc(wir, car);
seq = u3nc(ovo, seq);
}
/* insert with timestamp
*/
{
u3_noun all = seq;
pir_u->but_d += u3kb_lent(u3k(all));
while ( all ) {
_pier_insert_ovum(pir_u, 0, u3k(u3h(all)));
inx_w++;
all = u3t(all);
}
}
}
/* XX moar boot sequence woes
*/
{
// partially duplicates _pier_loop_wake()
//
c3_l cod_l;
cod_l = u3a_lush(c3__ames);
{
// stash domain for fake effect
// XX this is horrible
//
u3_noun tuf = ( c3__fake == u3h(pir_u->bot) ) ? u3_nul :
u3h(u3t(u3t(u3t(u3t(pir_u->bot)))));
// send a fake effect to bring up listeners and configure domains
// XX horrible hack
//
u3_ames_ef_turf(pir_u, u3k(tuf));
}
u3_ames_ef_bake(pir_u);
u3a_lop(cod_l);
cod_l = u3a_lush(c3__behn);
u3_behn_ef_bake(pir_u);
u3a_lop(cod_l);
}
/* insert legacy boot event
*/
{
u3_noun ovo;
/* make legacy boot event
*/
{
u3_noun wir = u3nq(u3_blip, c3__term, '1', u3_nul);
c3_assert( 0 != pir_u->bot);
ovo = u3nt(wir, c3__boot, pir_u->bot);
pir_u->bot = 0;
}
_pier_insert_ovum(pir_u, 0, ovo);
}
/* insert filesystem install events
*/
{
u3_noun all = fil;
while ( all ) {
_pier_insert_ovum(pir_u, 0, u3k(u3h(all)));
all = u3t(all);
}
}
u3z(who);
if ( c3y == u3h(pir_u->pil) ) {
u3x_trel(pir_u->pil, 0, &pil_p, &pil_q);
}
else {
u3x_qual(pir_u->pil, 0, &pil_p, &pil_q, &pil_r);
}
u3z(lal);
pro = u3m_soft(0, u3ke_cue, u3k(pil_p));
if ( 0 != u3h(pro) ) {
fprintf(stderr, "boot: failed: unable to parse pill\r\n");
exit(1);
}
u3x_trel(u3t(pro), &bot, &mod, &use);
u3k(bot); u3k(mod); u3k(use);
// optionally replace filesystem in userspace
//
if ( c3y == u3h(pir_u->pil) ) {
if ( u3_nul != pil_q ) {
c3_w len_w = 0;
u3_noun ova = use;
u3_noun new = u3_nul;
u3_noun ovo;
while ( u3_nul != ova ) {
ovo = u3h(ova);
if ( c3__into == u3h(u3t(ovo)) ) {
c3_assert( 0 == len_w );
len_w++;
ovo = u3k(u3t(pil_q));
}
new = u3nc(u3k(ovo), new);
ova = u3t(ova);
}
c3_assert( 1 == len_w );
u3z(use);
use = u3kb_flop(new);
}
}
// prepend %lite module and userspace ova
//
else {
mod = u3kb_weld(u3k(pil_q), mod);
use = u3kb_weld(u3k(pil_r), use);
}
u3z(pro);
u3z(pir_u->pil);
pir_u->pil = u3_nul;
}
// prepend entropy to the module sequence
//
// XX also copy to _pier_loop_wake?
//
{
c3_w eny_w[16];
c3_rand(eny_w);
u3_noun wir = u3nt(u3_blip, c3__arvo, u3_nul);
u3_noun car = u3nc(c3__wack, u3i_words(16, eny_w));
mod = u3nc(u3nc(wir, car), mod);
}
// prepend identity to the module sequence, setting single-home
//
{
u3_noun wir = u3nt(u3_blip, c3__arvo, u3_nul);
u3_noun car = u3nc(c3__whom, u3i_chubs(2, pir_u->who_d));
mod = u3nc(u3nc(wir, car), mod);
}
// insert boot sequence directly
//
// Note that these are not ovum or (pair @da ovum) events,
// but raw nock formulas to be directly evaluated as the
// subject of the lifecycle formula [%2 [%0 3] %0 2].
// All subsequent events will be (pair @da ovum).
//
{
u3_noun fol = bot;
// initialize the boot barrier
//
// And the initial lifecycle boot barrier.
//
pir_u->but_d = u3kb_lent(u3k(fol));
pir_u->lif_d = pir_u->but_d;
while ( u3_nul != fol ) {
_pier_insert(pir_u, 0, u3k(u3h(fol)));
fol = u3t(fol);
}
}
// prepare serf for boot sequence
//
{
pir_u->fak_o = ( c3__fake == u3h(pir_u->bot) ) ? c3y : c3n;
fprintf(stderr, "boot: ship: %s%s\r\n",
pir_u->who_c,
(c3y == pir_u->fak_o) ? " (fake)" : "");
_pier_work_boot(pir_u, c3y);
}
// insert module events
//
{
u3_noun ova = mod;
// add to the boot barrier
//
pir_u->but_d += u3kb_lent(u3k(ova));
while ( u3_nul != ova ) {
_pier_insert_ovum(pir_u, 0, u3k(u3h(ova)));
ova = u3t(ova);
}
}
// XX moar boot sequence woes
//
// some i/o must be initialized before legacy boot
//
{
// partially duplicates _pier_loop_wake()
//
c3_l cod_l;
cod_l = u3a_lush(c3__ames);
{
// stash domain for fake effect
//
// XX this is horrible
//
u3_noun tuf = ( c3__fake == u3h(pir_u->bot) ) ? u3_nul :
u3h(u3t(u3t(u3t(u3t(pir_u->bot)))));
// send a fake effect to bring up listeners and configure domains
//
// XX horrible hack
//
u3_ames_ef_turf(pir_u, u3k(tuf));
}
u3_ames_ef_bake(pir_u);
u3a_lop(cod_l);
cod_l = u3a_lush(c3__behn);
u3_behn_ef_bake(pir_u);
u3a_lop(cod_l);
}
// insert legacy boot event
//
{
// XX do something about this wire
// XX route directly to %jael?
//
c3_assert( c3y == u3du(pir_u->bot) );
u3_noun wir = u3nq(u3_blip, c3__term, '1', u3_nul);
u3_noun car = u3nc(c3__boot, pir_u->bot);
u3_noun ovo = u3nc(wir, car);
_pier_insert_ovum(pir_u, 0, ovo);
pir_u->bot = u3_nul;
}
// insert userspace events
//
// Currently just the initial filesystem
//
{
u3_noun ova = use;
while ( u3_nul != ova ) {
_pier_insert_ovum(pir_u, 0, u3k(u3h(ova)));
ova = u3t(ova);
}
}
u3z(bot); u3z(mod); u3z(use);
}
/* _pier_disk_consolidate(): integrate loaded information.
@ -1323,8 +1464,8 @@ _pier_work_poke(void* vod_p,
pir_u->who_d[0] = who_d[0];
pir_u->who_d[1] = who_d[1];
/* Disable networking for fake ships
*/
// Disable networking for fake ships
//
if ( c3y == pir_u->fak_o ) {
u3_Host.ops_u.net = c3n;
}
@ -1492,58 +1633,38 @@ _pier_work_create(u3_pier* pir_u)
/* u3_pier_create(): create a pier, loading existing.
*/
u3_pier*
u3_pier_create(c3_w wag_w, c3_c* pax_c, c3_c* sys_c)
u3_pier_create(c3_w wag_w, c3_c* pax_c)
{
u3_pier* pir_u;
// create pier
//
u3_pier* pir_u = c3_calloc(sizeof *pir_u);
/* create pier
*/
{
pir_u = c3_calloc(sizeof *pir_u);
pir_u->pax_c = pax_c;
pir_u->wag_w = wag_w;
pir_u->pax_c = c3_malloc(1 + strlen(pax_c));
strcpy(pir_u->pax_c, pax_c);
pir_u->sam_u = c3_calloc(sizeof(u3_ames));
pir_u->teh_u = c3_calloc(sizeof(u3_behn));
pir_u->unx_u = c3_calloc(sizeof(u3_unix));
pir_u->sav_u = c3_calloc(sizeof(u3_save));
if ( 0 != sys_c ) {
pir_u->sys_c = c3_malloc(1 + strlen(sys_c));
strcpy(pir_u->sys_c, sys_c);
}
pir_u->wag_w = wag_w;
pir_u->gen_d = 0;
pir_u->key_d[0] = pir_u->key_d[1] = pir_u->key_d[2] = pir_u->key_d[3] = 0;
pir_u->ent_u = pir_u->ext_u = 0;
pir_u->log_u = 0;
pir_u->god_u = 0;
pir_u->sam_u = c3_calloc(sizeof(u3_ames));
pir_u->teh_u = c3_calloc(sizeof(u3_behn));
pir_u->unx_u = c3_calloc(sizeof(u3_unix));
pir_u->sav_u = c3_calloc(sizeof(u3_save));
// start the serf process
//
if ( !(pir_u->god_u = _pier_work_create(pir_u)) ) {
return 0;
}
/* start process
*/
{
if ( !(pir_u->god_u = _pier_work_create(pir_u)) ) {
return 0;
}
// install in the pier table
//
if ( 0 == u3K.all_w ) {
u3K.all_w = 16;
u3K.tab_u = c3_malloc(16 * sizeof(u3_pier*));
}
if ( u3K.len_w == u3K.all_w ) {
u3K.all_w = 2 * u3K.all_w;
u3K.tab_u = c3_realloc(u3K.tab_u, u3K.all_w * sizeof(u3_pier*));
}
u3K.tab_u[u3K.len_w++] = pir_u;
/* install in pier table
*/
{
if ( 0 == u3K.all_w ) {
u3K.all_w = 16;
u3K.tab_u = c3_malloc(16 * sizeof(u3_pier*));
}
if ( u3K.len_w == u3K.all_w ) {
u3K.all_w = 2 * u3K.all_w;
u3K.tab_u = c3_realloc(u3K.tab_u, u3K.all_w * sizeof(u3_pier*));
}
u3K.tab_u[u3K.len_w++] = pir_u;
}
return pir_u;
}
@ -1869,14 +1990,23 @@ _pier_boot_complete(u3_pier* pir_u,
pir_u->god_u->dun_d,
(c3y == nuu_o ? "new" : "old"));
u3_pier_work_save(pir_u);
// start event replay by preparing serf to %boot
//
if ( (0 == pir_u->god_u->dun_d) &&
(c3n == nuu_o) )
{
_pier_work_boot(pir_u, c3n);
}
else {
u3_pier_work_save(pir_u);
}
/* the main course
*/
// the main course
//
_pier_loop_wake(pir_u);
/* where does this go, not sure?
*/
// XX where should this go?
//
{
if ( c3y == u3_Host.ops_u.veb ) {
u3_term_ef_verb();
@ -2013,85 +2143,55 @@ u3_pier_stub(void)
}
}
/* _pier_boot_make(): create/load a pier.
*/
static u3_pier*
_pier_boot_make(c3_w wag_w, u3_noun pax, u3_noun sys)
{
c3_c* pax_c = u3r_string(pax);
c3_c* sys_c;
u3_pier* pir_u;
if ( u3_nul == sys ) {
sys_c = 0;
}
else {
c3_assert( c3y == u3h(sys) );
sys_c = u3r_string(u3t(sys));
}
pir_u = u3_pier_create(wag_w, pax_c, sys_c);
u3z(pax); free(pax_c);
u3z(sys); free(sys_c);
pir_u->por_s = 0;
return pir_u;
}
/* u3_pier_boot(): start the new pier system.
*/
void
u3_pier_boot(c3_w wag_w, // config flags
u3_pier_boot(c3_w wag_w, // config flags
u3_noun who, // identity
u3_noun ven, // boot event
u3_noun pil, // type-of/path-to pill
u3_noun pax) // path to pier
{
u3_pier* pir_u;
// make/load pier
//
u3_pier* pir_u = u3_pier_create(wag_w, u3r_string(pax));
/* make/load pier
*/
pir_u = _pier_boot_make(wag_w, pax, pil);
/* set boot params
*/
// set boot params
//
{
{
u3_noun how = u3dc("scot", 'p', u3k(who));
pir_u->who_c = u3r_string(how);
u3z(how);
fprintf(stderr, "boot: ship: %s\r\n", pir_u->who_c);
}
u3r_chubs(0, 2, pir_u->who_d, who);
// u3r_chubs(0, 1, pir_u->tic_d, tic);
// u3r_chubs(0, 1, pir_u->sec_d, sec);
pir_u->bot = ven;
u3z(who);
// u3z(tic);
// u3z(sec);
pir_u->bot = u3k(ven);
pir_u->pil = u3k(pil);
}
/* initialize boot i/o
*/
// initialize boot i/o
//
_pier_loop_init_pier(pir_u);
/* initialize polling handle
*/
// initialize polling handle
//
uv_prepare_init(u3_Host.lup_u, &pir_u->pep_u);
uv_prepare_start(&pir_u->pep_u, _pier_loop_prepare);
/* initialize loop - move to _pier_boot_make().
*/
// initialize loop
//
_pier_loop_init();
/* XX: _pier_loop_exit() should be called somewhere, but is not.
*/
// XX: _pier_loop_exit() should be called somewhere, but is not.
//
u3z(who);
u3z(ven);
u3z(pil);
u3z(pax);
}
/* u3_pier_stay(): resume the new pier system.
@ -2099,25 +2199,27 @@ u3_pier_boot(c3_w wag_w, // config flags
void
u3_pier_stay(c3_w wag_w, u3_noun pax)
{
u3_pier* pir_u;
// make/load pier
//
u3_pier* pir_u = u3_pier_create(wag_w, u3r_string(pax));
/* make/load pier
*/
pir_u = _pier_boot_make(wag_w, pax, u3_nul);
// initialize boot i/o
//
_pier_loop_init_pier(pir_u);
/* initialize polling handle
*/
// initialize polling handle
//
uv_prepare_init(u3_Host.lup_u, &pir_u->pep_u);
uv_prepare_start(&pir_u->pep_u, _pier_loop_prepare);
_pier_loop_init_pier(pir_u);
/* initialize loop - move to _pier_boot_make().
*/
// initialize loop
//
_pier_loop_init();
/* XX: _pier_loop_exit() should be called somewhere, but is not.
*/
// XX: _pier_loop_exit() should be called somewhere, but is not.
//
u3z(pax);
}
/* u3_pier_mark(): mark all Loom allocations in all u3_pier structs.

View File

@ -872,6 +872,135 @@ _unix_update_mount(u3_pier *pir_u, u3_umon* mon_u, u3_noun all)
}
}
/* _unix_initial_update_file(): read file, but don't watch
** XX deduplicate with _unix_update_file()
*/
static u3_noun
_unix_initial_update_file(c3_c* pax_c, c3_c* bas_c)
{
struct stat buf_u;
c3_i fid_i = open(pax_c, O_RDONLY, 0644);
c3_ws len_ws, red_ws;
c3_y* dat_y;
if ( fid_i < 0 || fstat(fid_i, &buf_u) < 0 ) {
if ( ENOENT == errno ) {
return u3_nul;
}
else {
uL(fprintf(uH, "error opening initial file %s: %s\r\n",
pax_c, strerror(errno)));
return u3_nul;
}
}
len_ws = buf_u.st_size;
dat_y = c3_malloc(len_ws);
red_ws = read(fid_i, dat_y, len_ws);
if ( close(fid_i) < 0 ) {
uL(fprintf(uH, "error closing initial file %s: %s\r\n",
pax_c, strerror(errno)));
}
if ( len_ws != red_ws ) {
if ( red_ws < 0 ) {
uL(fprintf(uH, "error reading initial file %s: %s\r\n",
pax_c, strerror(errno)));
}
else {
uL(fprintf(uH, "wrong # of bytes read in initial file %s: %d %d\r\n",
pax_c, len_ws, red_ws));
}
free(dat_y);
return u3_nul;
}
else {
u3_noun pax = _unix_string_to_path_helper(pax_c
+ strlen(bas_c)
+ 1); /* XX slightly less VERY BAD than before*/
u3_noun mim = u3nt(c3__text, u3i_string("plain"), u3_nul);
u3_noun dat = u3nt(mim, len_ws, u3i_bytes(len_ws, dat_y));
free(dat_y);
return u3nc(u3nt(pax, u3_nul, dat), u3_nul);
}
}
/* _unix_initial_update_dir(): read directory, but don't watch
** XX deduplicate with _unix_update_dir()
*/
static u3_noun
_unix_initial_update_dir(c3_c* pax_c, c3_c* bas_c)
{
u3_noun can = u3_nul;
DIR* rid_u = opendir(pax_c);
if ( !rid_u ) {
uL(fprintf(uH, "error opening initial directory: %s: %s\r\n",
pax_c, strerror(errno)));
return u3_nul;
}
while ( 1 ) {
struct dirent ent_u;
struct dirent* out_u;
c3_w err_w;
if ( 0 != (err_w = readdir_r(rid_u, &ent_u, &out_u)) ) {
uL(fprintf(uH, "error loading initial directory %s: %s\r\n",
pax_c, strerror(errno)));
c3_assert(0);
}
else if ( !out_u ) {
break;
}
else if ( '.' == out_u->d_name[0] ) {
continue;
}
else {
c3_c* pox_c = _unix_down(pax_c, out_u->d_name);
struct stat buf_u;
if ( 0 != stat(pox_c, &buf_u) ) {
uL(fprintf(uH, "initial can't stat %s: %s\r\n",
pox_c, strerror(errno)));
free(pox_c);
continue;
}
else {
if ( S_ISDIR(buf_u.st_mode) ) {
can = u3kb_weld(_unix_initial_update_dir(pox_c, bas_c), can);
}
else {
can = u3kb_weld(_unix_initial_update_file(pox_c, bas_c), can);
}
free(pox_c);
}
}
}
if ( closedir(rid_u) < 0 ) {
uL(fprintf(uH, "error closing initial directory %s: %s\r\n",
pax_c, strerror(errno)));
}
return can;
}
/* u3_unix_initial_into_card(): create initial filesystem sync card.
*/
u3_noun
u3_unix_initial_into_card(c3_c* arv_c)
{
u3_noun can = _unix_initial_update_dir(arv_c, arv_c);
return u3nc(u3nt(u3_blip, c3__sync, u3_nul),
u3nq(c3__into, u3_nul, c3y, can));
}
/* _unix_sign_cb: signal callback.
*/
static void