Updates
This commit is contained in:
+9
-9
@@ -4,22 +4,22 @@ Files in this directory are **read from disk by the seeder** (or copied into `pa
|
||||
|
||||
## Staging map (seeder)
|
||||
|
||||
| Source | Drive path |
|
||||
| ----------------- | --------------------- |
|
||||
| `init.js` | `/boot/init.js` |
|
||||
| `bin/<name>` | `/bin/<name>` |
|
||||
| `etc/...` | `/etc/...` |
|
||||
| `share/man/...` | `/share/man/...` |
|
||||
| Any other file | `/<relative path>` |
|
||||
| Source | Drive path |
|
||||
| --------------- | ------------------ |
|
||||
| `init.js` | `/boot/init.js` |
|
||||
| `bin/<name>` | `/bin/<name>` |
|
||||
| `etc/...` | `/etc/...` |
|
||||
| `share/man/...` | `/share/man/...` |
|
||||
| Any other file | `/<relative path>` |
|
||||
|
||||
## Contents
|
||||
|
||||
- **`init.js`** — Kernel entry: must define `async function start(ctx)`. Boot order: **`/etc/os-release`** → **`/etc/motd`** → optional **`/etc/bare-os/rc.profile.<profile>`** (profile from **`BARE_OS_BOOT_PROFILE`** or first line of **`/etc/bare-os/profile`**) → **`/etc/bare-os/rc`** → **`/etc/bare-os/rc.d/*`** (sorted; only names starting with a digit, plus skips dotfiles, `*~`, `README*`, `*.md`) → banner → when **`BARE_OS_SKIP_REPL`**, optional one line from **`BARE_OS_ONBOOT`** or **`/etc/bare-os/onboot`** → **`readLine` / `execLine`** loop (boot snippet errors are logged, not fatal). Custom kernels may call **`ctx.registerKernelShutdownHook(fn)`** before initd disposers; use **`ctx.bareOsRuntimeCaps`** for limits and pseudo path lists ([`developer-guide/02-the-context-object.md`](../developer-guide/02-the-context-object.md)).
|
||||
- **`init.js`** — Kernel entry: must define `async function start(ctx)`. Boot order: **`/etc/os-release`** → **`/etc/motd`** → optional **`/etc/bare-os/rc.profile.<profile>`** (profile from **`BARE_OS_BOOT_PROFILE`** or first line of **`/etc/bare-os/profile`**) → **`/etc/bare-os/rc`** → **`/etc/bare-os/rc.d/*`** (sorted; only names starting with a digit, plus skips dotfiles, `*~`, `README*`, `*.md`) → optional **`/etc/bare-os/rc.local`** → banner → when **`BARE_OS_SKIP_REPL`**, optional **onboot** lines from **`BARE_OS_ONBOOT`** (newline-separated) or **`/etc/bare-os/onboot`** (file order) → **`readLine` / `execLine`** loop (boot snippet errors are logged, not fatal). Custom kernels may call **`ctx.registerKernelShutdownHook(fn)`** before initd disposers; use **`ctx.bareOsRuntimeCaps`** for limits, pseudo paths, and **`features`** ([`developer-guide/02-the-context-object.md`](../developer-guide/02-the-context-object.md)).
|
||||
- **`bin/`** — **Tier-1 utilities** built by [bare-os-coreutils](../packages/bare-os-coreutils/README.md). Each file is **`runtime.js`** + optional **`lib/*-engine.js`** (**`sed`**, **`awk`**) or **`lib/man-render.js`** (**`man`**) + **`async function run(ctx, argv)`** (no ESM **`import`** in **`src/`**).
|
||||
- **`share/man/man.json`** — Merged manual database for **`/bin/man`** (built by **`bare-os-coreutils`**; see [handbook ch.10](../handbook/10-manpages-and-online-help.md)).
|
||||
- **`etc/os-release`** — Static OS metadata (`NAME`, `VERSION`, …).
|
||||
- **`etc/motd`** — Optional message printed after **`os-release`** (distributors can customize).
|
||||
- **`etc/bare-os/banner`** or **`/etc/issue`** — If present on the system drive, the default kernel prints one of these instead of the built-in session hint (unless **`BARE_OS_SKIP_REPL`** shortens the banner). Set **`BARE_OS_BOOT_TRACE=1`** in the session environment to log boot phase timings on stderr.
|
||||
- **`etc/bare-os/banner`** or **`/etc/issue`** — If present on the system drive, the default kernel prints one of these instead of the built-in session hint (unless **`BARE_OS_SKIP_REPL`** shortens the banner). Set **`BARE_OS_BOOT_TRACE=1`** or **`true`** for **`[boot] phase: Nms`** lines on stderr, or **`json`** for **`{"phase":"…","ms":n}`** per phase.
|
||||
- **`etc/bare-os/rc`** — Optional boot snippet: one **`execLine`** per non-comment line (trusted).
|
||||
- **`etc/bare-os/rc.d/`** — Optional extra snippets (basename must start with a digit), same line rules, run after **`rc`** in filename order. Human-oriented notes live in **`.README`** (a dotfile so legacy **`init.js`** never executes it).
|
||||
|
||||
|
||||
+23
-5
@@ -60,7 +60,11 @@ function barePosixBlocks(size) {
|
||||
return Math.ceil(Number(size) / 512) || 0
|
||||
}
|
||||
|
||||
async function walk(ctx, dir, nameRe, wantType, maxDepth, curDepth) {
|
||||
/**
|
||||
* curDepth is distance from the search root directory (0 at the initial path).
|
||||
* Printed paths use gnu-like depth curDepth + 1 (immediate children of the root are depth 1).
|
||||
*/
|
||||
async function walk(ctx, dir, nameRe, wantType, maxDepth, minDepth, curDepth) {
|
||||
if (maxDepth >= 0 && curDepth > maxDepth) return
|
||||
let names
|
||||
try {
|
||||
@@ -78,15 +82,21 @@ async function walk(ctx, dir, nameRe, wantType, maxDepth, curDepth) {
|
||||
continue
|
||||
}
|
||||
if (!st) continue
|
||||
const gnuDepth = curDepth + 1
|
||||
if (!nameRe || nameRe.test(n)) {
|
||||
if (!wantType || st.type === wantType) ctx.console.log(path)
|
||||
if (!wantType || st.type === wantType) {
|
||||
if (gnuDepth >= minDepth) ctx.console.log(path)
|
||||
}
|
||||
}
|
||||
if (st.type === 'directory') await walk(ctx, path, nameRe, wantType, maxDepth, curDepth + 1)
|
||||
if (st.type === 'directory')
|
||||
await walk(ctx, path, nameRe, wantType, maxDepth, minDepth, curDepth + 1)
|
||||
}
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
let maxDepth = -1
|
||||
/** Minimum path depth below the search root (1 = default; same as GNU -mindepth 1 for tree walks). */
|
||||
let minDepth = 1
|
||||
/** @type {string | null} */
|
||||
let nameGlob = null
|
||||
/** @type {'file' | 'directory' | 'symlink' | null} */
|
||||
@@ -98,6 +108,11 @@ async function run(ctx, argv) {
|
||||
maxDepth = Number.parseInt(argv[++i], 10)
|
||||
continue
|
||||
}
|
||||
if (a === '-mindepth' && argv[i + 1]) {
|
||||
minDepth = Number.parseInt(argv[++i], 10)
|
||||
if (!Number.isFinite(minDepth) || minDepth < 1) minDepth = 1
|
||||
continue
|
||||
}
|
||||
if (a === '-name' && argv[i + 1]) {
|
||||
nameGlob = argv[++i]
|
||||
continue
|
||||
@@ -123,9 +138,12 @@ async function run(ctx, argv) {
|
||||
const root = rest[0] || '.'
|
||||
let nameRe = null
|
||||
if (nameGlob) {
|
||||
const esc = nameGlob.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*').replace(/\?/g, '.')
|
||||
const esc = nameGlob
|
||||
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
||||
.replace(/\*/g, '.*')
|
||||
.replace(/\?/g, '.')
|
||||
nameRe = new RegExp('^' + esc + '$')
|
||||
}
|
||||
const abs = ctx.vfs.resolveLogical(root)
|
||||
await walk(ctx, abs, nameRe, wantType, maxDepth, 0)
|
||||
await walk(ctx, abs, nameRe, wantType, maxDepth, minDepth, 0)
|
||||
}
|
||||
|
||||
+41
-18
@@ -3,14 +3,17 @@
|
||||
* Loaded by the booter with an injected ctx object (trusted replication source).
|
||||
*
|
||||
* Boot order: /etc/os-release → /etc/motd → optional profile rc → /etc/bare-os/rc →
|
||||
* /etc/bare-os/rc.d/* (sorted; digit-prefixed snippet names) → session banner →
|
||||
* optional oneshot onboot when BARE_OS_SKIP_REPL → interactive loop.
|
||||
* /etc/bare-os/rc.d/* (sorted; digit-prefixed snippet names) → /etc/bare-os/rc.local →
|
||||
* session banner → optional onboot lines when BARE_OS_SKIP_REPL → interactive loop.
|
||||
*
|
||||
* Profile: first non-empty line of /etc/bare-os/profile, overridden by BARE_OS_BOOT_PROFILE.
|
||||
* When set, runs /etc/bare-os/rc.profile.<name> if present (trusted execLine, before main rc).
|
||||
*
|
||||
* Non-interactive onboot: when ctx.bareOsSkipRepl, runs one line from BARE_OS_ONBOOT env
|
||||
* or first non-empty, non-# line from /etc/bare-os/onboot (trusted), then readLine yields EOF.
|
||||
* Non-interactive onboot: when ctx.bareOsSkipRepl, runs each non-empty, non-# line from
|
||||
* BARE_OS_ONBOOT (newline-separated) or, if unset, every such line from /etc/bare-os/onboot
|
||||
* in file order (trusted). Then readLine yields EOF.
|
||||
*
|
||||
* BARE_OS_BOOT_TRACE=json logs one JSON object per phase on stderr: {"phase":"…","ms":n}.
|
||||
*
|
||||
* Use ctx.registerKernelShutdownHook(fn) for teardown before initd disposers.
|
||||
*/
|
||||
@@ -20,7 +23,14 @@
|
||||
*/
|
||||
function wantBootTrace(ctx) {
|
||||
const v = ctx.env && ctx.env.BARE_OS_BOOT_TRACE
|
||||
return v === '1' || v === 'true'
|
||||
return v === '1' || v === 'true' || v === 'json'
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Record<string, unknown>} ctx
|
||||
*/
|
||||
function isBootTraceJson(ctx) {
|
||||
return ctx.env && ctx.env.BARE_OS_BOOT_TRACE === 'json'
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -32,7 +42,12 @@ async function bootTimed(ctx, label, fn) {
|
||||
const t0 = Date.now()
|
||||
await fn()
|
||||
if (wantBootTrace(ctx)) {
|
||||
ctx.console.error(`[boot] ${label}: ${Date.now() - t0}ms`)
|
||||
const ms = Date.now() - t0
|
||||
if (isBootTraceJson(ctx)) {
|
||||
ctx.console.error(JSON.stringify({ phase: label, ms }))
|
||||
} else {
|
||||
ctx.console.error(`[boot] ${label}: ${ms}ms`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,16 +135,21 @@ async function runProfileRc(ctx, profileName) {
|
||||
}
|
||||
|
||||
/**
|
||||
* When stdin is non-interactive, run a single trusted boot command (automation).
|
||||
* When stdin is non-interactive, run trusted boot commands (automation).
|
||||
* @param {Record<string, unknown>} ctx
|
||||
*/
|
||||
async function runOnbootOnce(ctx) {
|
||||
async function runOnboot(ctx) {
|
||||
if (!ctx.bareOsSkipRepl) return
|
||||
const { execLine, console, drive, b4a, env } = ctx
|
||||
let line = ''
|
||||
/** @type {string[]} */
|
||||
const lines = []
|
||||
const fromEnv = env && env.BARE_OS_ONBOOT
|
||||
if (fromEnv != null && String(fromEnv).trim()) {
|
||||
line = String(fromEnv).trim()
|
||||
for (const raw of String(fromEnv).split(/\r?\n/)) {
|
||||
const t = raw.trim()
|
||||
if (!t || t.startsWith('#')) continue
|
||||
lines.push(t)
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const buf = await drive.get('/etc/bare-os/onboot')
|
||||
@@ -137,19 +157,19 @@ async function runOnbootOnce(ctx) {
|
||||
for (const raw of b4a.toString(buf).split(/\r?\n/)) {
|
||||
const t = raw.trim()
|
||||
if (!t || t.startsWith('#')) continue
|
||||
line = t
|
||||
break
|
||||
lines.push(t)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('onboot: ' + ((e && e.message) || String(e)))
|
||||
}
|
||||
}
|
||||
if (!line) return
|
||||
try {
|
||||
await execLine(line)
|
||||
} catch (e) {
|
||||
console.error((e && e.message) || String(e))
|
||||
for (const line of lines) {
|
||||
try {
|
||||
await execLine(line)
|
||||
} catch (e) {
|
||||
console.error((e && e.message) || String(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,8 +267,11 @@ async function start(ctx) {
|
||||
await bootTimed(ctx, 'rc.profile', () => runProfileRc(ctx, profileName))
|
||||
await bootTimed(ctx, 'rc', () => runRcFileAt(ctx, '/etc/bare-os/rc', 'rc'))
|
||||
await bootTimed(ctx, 'rc.d', () => runBareOsRcDir(ctx))
|
||||
await bootTimed(ctx, 'rc.local', () =>
|
||||
runRcFileAt(ctx, '/etc/bare-os/rc.local', 'rc.local')
|
||||
)
|
||||
await printSessionBanner(ctx)
|
||||
await bootTimed(ctx, 'onboot', () => runOnbootOnce(ctx))
|
||||
await bootTimed(ctx, 'onboot', () => runOnboot(ctx))
|
||||
while (true) {
|
||||
const line = await readLine('')
|
||||
if (line == null) break
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user