buninu-linux 0.3.1 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSES/Apache-2.0.txt +202 -0
- package/LICENSES/BSD-3-Clause-Skia.txt +29 -0
- package/LICENSES/Bitstream-Vera.txt +44 -0
- package/LICENSES/MIT-xterm.js.txt +21 -0
- package/LICENSES/OFL-1.1.txt +91 -0
- package/NOTICE.md +18 -1
- package/README.md +101 -9
- package/fetch-alpine.sh +6 -0
- package/graphics.md +218 -0
- package/initramfs/bin/bunterm +70 -0
- package/initramfs/bin/chroot +213 -0
- package/initramfs/bin/stripansi +27 -0
- package/initramfs/bin/tar +189 -14
- package/initramfs/buninu/CHANGELOG.md +40 -0
- package/initramfs/buninu/apps/jsgotty/gotty.js +4 -3
- package/initramfs/buninu/apps/jsgotty/package.json +1 -1
- package/initramfs/buninu/package.json +1 -1
- package/initramfs/init.js +80 -1
- package/initramfs/lib/bunterm/glyphs.js +446 -0
- package/initramfs/lib/bunterm/images.js +225 -0
- package/initramfs/lib/bunterm/input.js +140 -0
- package/initramfs/lib/bunterm/mouse.js +222 -0
- package/initramfs/lib/bunterm/renderer.js +469 -0
- package/initramfs/lib/bunterm/terminal.js +324 -0
- package/initramfs/lib/canvas.js +181 -0
- package/initramfs/lib/canvaskit/LICENSE +29 -0
- package/initramfs/lib/canvaskit/canvaskit.js +264 -0
- package/initramfs/lib/canvaskit/canvaskit.wasm +0 -0
- package/initramfs/lib/dlopen.js +18 -2
- package/initramfs/lib/document.js +5 -1
- package/initramfs/lib/fbdev.js +581 -0
- package/initramfs/lib/xterm/LICENSE +21 -0
- package/initramfs/lib/xterm/addon-unicode-graphemes.mjs +44 -0
- package/initramfs/lib/xterm/xterm-headless.mjs +46 -0
- package/initramfs/usr/share/doc/buninu-linux/bunterm.md +112 -0
- package/initramfs/usr/share/doc/buninu-linux/canvas.md +91 -0
- package/initramfs/usr/share/doc/buninu-linux/chroot.md +105 -0
- package/initramfs/usr/share/doc/buninu-linux/fbdev.md +113 -0
- package/initramfs/usr/share/doc/buninu-linux/tar.md +30 -6
- package/initramfs/usr/share/fonts/DejaVuSansMono-Bold.ttf +0 -0
- package/initramfs/usr/share/fonts/DejaVuSansMono.ttf +0 -0
- package/initramfs/usr/share/fonts/LICENSE-Apache-2.0.txt +202 -0
- package/initramfs/usr/share/fonts/LICENSE-DejaVu.txt +44 -0
- package/initramfs/usr/share/fonts/LICENSE-OFL-1.1.txt +91 -0
- package/initramfs/usr/share/fonts/NotoColorEmoji.ttf +0 -0
- package/initramfs/usr/share/fonts/NotoColorEmojiFlags.ttf +0 -0
- package/initramfs/usr/share/fonts/NotoSansCJK-Regular.ttc +0 -0
- package/initramfs/usr/share/fonts/NotoSansSymbols-Regular-Subsetted.ttf +0 -0
- package/initramfs/usr/share/fonts/NotoSansSymbols-Regular-Subsetted2.ttf +0 -0
- package/initramfs/usr/share/fonts/Roboto-Regular.ttf +0 -0
- package/initramfs/usr/share/fonts/fonts.json +28 -0
- package/package.json +2 -2
- package/run-qemu.sh +1 -1
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# bunterm — a graphical terminal on the Linux framebuffer
|
|
2
|
+
|
|
3
|
+
`bunterm` runs a program on a pseudo-terminal and draws its screen on
|
|
4
|
+
`/dev/fb0` with Skia (CanvasKit), so a real Linux console gets an
|
|
5
|
+
xterm-compatible terminal with anti-aliased text, CJK, colour emoji, seamless
|
|
6
|
+
box drawing and kitty graphics protocol images — no X11, Wayland or GPU.
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
bunterm # run /bin/sh on the console you are on
|
|
10
|
+
bunterm /dev/tty1 # use virtual console 1 for graphics and keys
|
|
11
|
+
bunterm --font-size 20
|
|
12
|
+
bunterm -e bun /buninu/apps/jsmdcui/src/index.js --demo
|
|
13
|
+
bunterm --no-mouse # keyboard only
|
|
14
|
+
bunterm -h
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The program's `TERM` is `xterm-256color`, `COLORTERM=truecolor`,
|
|
18
|
+
`TERM_PROGRAM=bunterm` and `JSMDCUI_KITTY_MODE=extended` (so `jsmdcui` shows
|
|
19
|
+
Markdown images without `--kitty`). When it exits, the console returns to
|
|
20
|
+
text mode and `bunterm` exits with its status.
|
|
21
|
+
|
|
22
|
+
## Options
|
|
23
|
+
|
|
24
|
+
| Option | Meaning |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| `/dev/ttyN` | The virtual console to use for graphics and the keyboard. If another console is on screen, the display switches to this one first and back when `bunterm` exits. Without it the process's own console and stdin are used, so run it from a VT (not a serial line or a PTY). |
|
|
27
|
+
| `-e command [argument...]` | The program to run; everything after `-e` belongs to it. Default `/bin/sh`. |
|
|
28
|
+
| `--font-size N` | Font size in pixels (default 16). The cell is 0.6 × N wide and 1.16 × N tall with DejaVu Sans Mono, so 1024×768 at 16 px gives 106 × 41 cells. |
|
|
29
|
+
| `--line-height F` | Multiplies the cell height (default 1). |
|
|
30
|
+
| `--fb /dev/fbN` | The framebuffer device (default `/dev/fb0`). |
|
|
31
|
+
| `--no-blink` | A steady cursor. |
|
|
32
|
+
| `--no-mouse` | Do not attach a pointing device; nothing then reads `/dev/input`. |
|
|
33
|
+
|
|
34
|
+
## What is drawn
|
|
35
|
+
|
|
36
|
+
- **Text** comes from `/usr/share/fonts`: DejaVu Sans Mono (regular and
|
|
37
|
+
bold) sets the grid; Noto Sans CJK TC, Noto Color Emoji (+ Flags) and Noto
|
|
38
|
+
Sans Symbols fill in what it lacks. A glyph is centred in the one or two
|
|
39
|
+
cells the terminal assigned it; wide characters take two.
|
|
40
|
+
- **Box drawing, block elements, shades and Powerline symbols** (U+2500–259F,
|
|
41
|
+
U+E0A0–E0BF, U+1FB70–1FB97) are drawn as vectors, ported from xterm.js, so
|
|
42
|
+
they join without seams at any size.
|
|
43
|
+
- **Attributes**: 16 / 256 / 24-bit colours, bold (brighter for the eight base
|
|
44
|
+
colours), italic, dim, underline, strikethrough, inverse, invisible.
|
|
45
|
+
- **Grapheme clusters** such as 🇹🇼 and 👨👩👧 occupy one cell each (xterm.js's
|
|
46
|
+
unicode-graphemes addon) and are shaped by Skia's paragraph engine.
|
|
47
|
+
- **Images**: the kitty graphics protocol (`ESC _ G … ESC \`) with direct
|
|
48
|
+
transmission (`t=d`), PNG (`f=100`) or raw RGB/RGBA (`f=24`/`32`), zlib
|
|
49
|
+
(`o=z`), chunking (`m=`), cropping (`x,y,w,h`), sizing in cells (`c,r`),
|
|
50
|
+
cell offsets (`X,Y`), placements (`p=`), deletion (`a=d`) and queries
|
|
51
|
+
(`a=q`). An image is anchored to its line and scrolls with the text; on the
|
|
52
|
+
alternate screen it stays at its row and is removed when the program
|
|
53
|
+
leaves that screen. Any encoding Skia decodes (PNG, JPEG, WebP, GIF) is
|
|
54
|
+
accepted under `f=100`, as with jsgotty's `U=` extension.
|
|
55
|
+
|
|
56
|
+
## Keyboard
|
|
57
|
+
|
|
58
|
+
The console stays in the kernel's translated keyboard mode, so
|
|
59
|
+
`Ctrl-Alt-F2` and friends still switch consoles; coming back repaints the
|
|
60
|
+
screen. A few console-specific
|
|
61
|
+
sequences are rewritten to xterm's (`F1`–`F5`, `Home`, `End`), and arrow keys
|
|
62
|
+
follow the program's application cursor mode.
|
|
63
|
+
|
|
64
|
+
## Mouse
|
|
65
|
+
|
|
66
|
+
Every pointing device under `/dev/input/event*` is opened and an arrow is
|
|
67
|
+
drawn on the screen. Clicks, drags and wheel notches reach the program as
|
|
68
|
+
the xterm mouse sequences it asked for: nothing is sent unless the program
|
|
69
|
+
enabled reporting (`DECSET 1000`, `1002` or `1003`), and what is sent follows
|
|
70
|
+
the mode it chose, SGR (`1006`) included. `jsmdcui`, `micro`, `htop`, `vim`
|
|
71
|
+
and anything else that speaks the protocol work with no configuration.
|
|
72
|
+
|
|
73
|
+
When the program is not reading the mouse, the wheel scrolls instead: back
|
|
74
|
+
through the scrollback on the normal screen, three lines per notch, and as
|
|
75
|
+
arrow keys on the alternate screen, which has no scrollback and is what a
|
|
76
|
+
pager expects. Typing returns to the live screen, and the text cursor is
|
|
77
|
+
hidden while it is scrolled out of view.
|
|
78
|
+
|
|
79
|
+
`--no-mouse` turns all of this off: the terminal then never looks at
|
|
80
|
+
`/dev/input` and never loads the mouse module.
|
|
81
|
+
|
|
82
|
+
`init.js` loads `evdev` and `psmouse` at boot, so a PS/2 mouse — which is
|
|
83
|
+
what QEMU's q35 machine and most PCs present — has a device node ready. A USB
|
|
84
|
+
mouse also needs the `usbhid` stack, which a `--real` image carries and
|
|
85
|
+
`cfg.all` loads. The pointer follows relative devices (a mouse) and absolute
|
|
86
|
+
ones (a tablet or touchscreen) alike; a device that cannot be opened is
|
|
87
|
+
reported and the session continues without it.
|
|
88
|
+
|
|
89
|
+
## Limits
|
|
90
|
+
|
|
91
|
+
- Needs a framebuffer: `linux-lts` has one built in, while the default
|
|
92
|
+
`linux-virt` builds it as modules the image does not ship, so build with
|
|
93
|
+
`--linux-lts` or `--real` (efifb/simpledrm from UEFI).
|
|
94
|
+
- No selection, and no keyboard way to scroll back: the wheel is it. The
|
|
95
|
+
buffer keeps 1000 lines. A program that does not enable mouse reporting
|
|
96
|
+
sees no clicks — the arrow still moves, so the pointer is visibly alive.
|
|
97
|
+
`--no-mouse` removes the pointer entirely.
|
|
98
|
+
- A program that prints a terminal reply while the tty echoes (that is, one
|
|
99
|
+
not in raw mode) will see the reply echoed, as on any terminal.
|
|
100
|
+
- Kitty images are drawn above text; `z` ordering below text and animation
|
|
101
|
+
frames are not implemented, and file transmission (`t=f`/`t=t`) works only
|
|
102
|
+
for files under `/tmp`, `/dev/shm` or `$TMPDIR`.
|
|
103
|
+
- One framebuffer, one session. For panes and tabs run `jsmdcui` inside it.
|
|
104
|
+
|
|
105
|
+
## See also
|
|
106
|
+
|
|
107
|
+
- `/lib/bunterm/terminal.js` — `createSession()` and `runTerminal()`, the
|
|
108
|
+
pieces `bunterm` is built from
|
|
109
|
+
- `/lib/canvas.js` — CanvasKit on the framebuffer (`canvas.md`)
|
|
110
|
+
- `/lib/fbdev.js` — the framebuffer itself (`fbdev.md`)
|
|
111
|
+
- `/buninu/apps/jsgotty/gotty.js` — the PTY backend and kitty packet parser
|
|
112
|
+
that are reused
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# canvas — CanvasKit (Skia) on the Linux framebuffer
|
|
2
|
+
|
|
3
|
+
`/lib/canvas.js` runs Skia, compiled to WebAssembly as CanvasKit, on top of
|
|
4
|
+
`/lib/fbdev.js`. Skia rasterizes straight into a buffer that already has the
|
|
5
|
+
framebuffer's pixel layout, so a frame reaches `/dev/fb0` with one `memcpy`
|
|
6
|
+
and no per-pixel conversion in JavaScript.
|
|
7
|
+
|
|
8
|
+
## Drawing with Skia
|
|
9
|
+
|
|
10
|
+
```js
|
|
11
|
+
import { runGraphics } from "/lib/fbdev.js";
|
|
12
|
+
import { loadCanvasKit, openCanvas, loadFontSet } from "/lib/canvas.js";
|
|
13
|
+
|
|
14
|
+
const CanvasKit = await loadCanvasKit();
|
|
15
|
+
const fonts = loadFontSet(CanvasKit, "ui");
|
|
16
|
+
|
|
17
|
+
await runGraphics(async (display, { onRestore }) => {
|
|
18
|
+
const screen = openCanvas(CanvasKit, display);
|
|
19
|
+
const paint = new CanvasKit.Paint();
|
|
20
|
+
paint.setAntiAlias(true);
|
|
21
|
+
paint.setColor(CanvasKit.Color(64, 200, 255));
|
|
22
|
+
const font = new CanvasKit.Font(fonts.regular, 32);
|
|
23
|
+
|
|
24
|
+
screen.canvas.clear(CanvasKit.BLACK);
|
|
25
|
+
screen.canvas.drawCircle(display.width / 2, display.height / 2, 120, paint);
|
|
26
|
+
screen.canvas.drawText("Buninu 你好 😀", 40, 60, paint, font);
|
|
27
|
+
screen.flush();
|
|
28
|
+
|
|
29
|
+
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
30
|
+
screen.close();
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`screen.canvas` is a Skia `Canvas` with the full CanvasKit API: paths,
|
|
35
|
+
gradients, shaders, image filters, `drawImage`, `drawGlyphs`, `Paragraph`
|
|
36
|
+
layout with font fallback, PNG/JPEG decoding, and so on.
|
|
37
|
+
|
|
38
|
+
## Exports
|
|
39
|
+
|
|
40
|
+
| Export | Purpose |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| `loadCanvasKit()` | Loads `/lib/canvaskit/canvaskit.wasm` once per process and resolves to the `CanvasKit` object. The wasm heap starts at 128 MiB. |
|
|
43
|
+
| `openCanvas(CanvasKit, display)` | Binds a raster surface to an open `Framebuffer`. Returns `{ canvas, surface, width, height, colorType, flush(), close() }`. While open, `display.pixels` is the surface's own memory, so `drawLine()`, `fillPolygon()` and `flush()` from `fbdev.js` keep working on the same frame. `close()` hands the last frame back to the JavaScript buffer. |
|
|
44
|
+
| `pickColorType(CanvasKit, display)` | The Skia `ColorType` matching the framebuffer: `BGRA_8888` for the usual 32-bit XRGB (efifb, simpledrm), `RGBA_8888`, `RGB_565`; `null` for anything else, which `openCanvas` rejects. |
|
|
45
|
+
| `loadFontSet(CanvasKit, name)` | A font set from `/usr/share/fonts/fonts.json` (`"terminal"` or `"ui"`) as `{ regular, bold, fallback, typefaces, fontMgr, families, delete() }`. `fontMgr` and `families` are what `ParagraphStyle` wants; a collection such as Noto Sans CJK registers every face and yields its preferred one (TC). |
|
|
46
|
+
| `fontCatalogue()`, `fontPath(name)`, `loadFontData(name)` | The parsed `fonts.json`, a font's path, and its bytes (cached). |
|
|
47
|
+
|
|
48
|
+
## Formats
|
|
49
|
+
|
|
50
|
+
The framebuffer reports its channels as bit offsets. Skia can rasterize
|
|
51
|
+
directly into three of the layouts Linux uses:
|
|
52
|
+
|
|
53
|
+
| Framebuffer | Skia |
|
|
54
|
+
| --- | --- |
|
|
55
|
+
| 32 bpp, red@16 green@8 blue@0 (XRGB8888) | `BGRA_8888` |
|
|
56
|
+
| 32 bpp, red@0 green@8 blue@16 (XBGR8888) | `RGBA_8888` |
|
|
57
|
+
| 16 bpp, 5-6-5 | `RGB_565` |
|
|
58
|
+
|
|
59
|
+
For a 24 bpp or paletted framebuffer, draw with the HTML canvas emulation
|
|
60
|
+
instead and copy through `blitImageData()`:
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
const canvas = CanvasKit.MakeCanvas(display.width, display.height);
|
|
64
|
+
const ctx = canvas.getContext("2d");
|
|
65
|
+
ctx.fillStyle = "#40c8ff";
|
|
66
|
+
ctx.fillRect(0, 0, 200, 100);
|
|
67
|
+
blitImageData(display, ctx.getImageData(0, 0, display.width, display.height));
|
|
68
|
+
flush(display);
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
That path converts every pixel in JavaScript and is fine for static screens.
|
|
72
|
+
|
|
73
|
+
## Fonts
|
|
74
|
+
|
|
75
|
+
`/usr/share/fonts/fonts.json` lists the bundled files and two sets:
|
|
76
|
+
|
|
77
|
+
| Set | Regular | Fallback order |
|
|
78
|
+
| --- | --- | --- |
|
|
79
|
+
| `terminal` | DejaVu Sans Mono (+ Bold) | Noto Color Emoji, Noto Color Emoji Flags, Noto Sans CJK, Noto Sans Symbols, Noto Sans Symbols2 |
|
|
80
|
+
| `ui` | Roboto | Noto Sans CJK, Noto Color Emoji, Noto Color Emoji Flags, Noto Sans Symbols, Noto Sans Symbols2 |
|
|
81
|
+
|
|
82
|
+
Files load on first use and are copied into the wasm heap; the CJK
|
|
83
|
+
collection is 32 MiB, so a program that never draws CJK text should not
|
|
84
|
+
load a set containing it. Each file's license sits beside it.
|
|
85
|
+
|
|
86
|
+
## See also
|
|
87
|
+
|
|
88
|
+
- `/lib/canvas.js`, `/lib/canvaskit/` (CanvasKit 0.41.1, BSD-3-Clause)
|
|
89
|
+
- `/lib/fbdev.js` — `fbdev.md`
|
|
90
|
+
- `/lib/bunterm/` — the terminal built on this (`bunterm.md`)
|
|
91
|
+
- CanvasKit API: https://skia.org/docs/user/modules/canvaskit/
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# chroot — run a command inside another root directory
|
|
2
|
+
|
|
3
|
+
`/bin/chroot` is a Bun script that calls `chroot(2)` and `mount(2)` through
|
|
4
|
+
`/lib/dlopen.js`.
|
|
5
|
+
|
|
6
|
+
Unlike the traditional `chroot`, it prepares the new root first, so a
|
|
7
|
+
freshly unpacked root filesystem is usable straight away, and it undoes
|
|
8
|
+
every mount it made when the command exits.
|
|
9
|
+
|
|
10
|
+
## Synopsis
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
chroot NEWROOT [COMMAND [ARGUMENT...]]
|
|
14
|
+
chroot [-n] [-k] [-v] NEWROOT [COMMAND [ARGUMENT...]]
|
|
15
|
+
chroot -h | --help
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
With no COMMAND it runs `$SHELL` if that exists inside NEWROOT, otherwise
|
|
19
|
+
`/bin/sh`, interactively when the terminal is one.
|
|
20
|
+
|
|
21
|
+
## What it mounts
|
|
22
|
+
|
|
23
|
+
| Inside NEWROOT | What | Why |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| `/proc` | a fresh `proc` | path resolution, `ps`, anything reading `/proc/self` |
|
|
26
|
+
| `/sys` | a fresh `sysfs` | device and network information |
|
|
27
|
+
| `/dev` | recursive bind of the host's `/dev`, made a slave mount | every device node, including `/dev/ptmx`, without a second devtmpfs |
|
|
28
|
+
| `/dev/pts` | `devpts`, only if the bind brought none | pseudo-terminals for shells and editors |
|
|
29
|
+
| `/run` | `tmpfs` | runtime state |
|
|
30
|
+
| `/tmp` | `tmpfs` | scratch space that does not touch the root filesystem |
|
|
31
|
+
| `/etc/resolv.conf` | bind of the host's file | name resolution, without editing anything inside |
|
|
32
|
+
|
|
33
|
+
A mount point that already exists as a mount is left alone. A directory that
|
|
34
|
+
is missing is created; if the root filesystem is read-only and that fails,
|
|
35
|
+
that one mount is skipped and the rest still happen — use `-v` to see which.
|
|
36
|
+
|
|
37
|
+
Making `/dev` a slave mount means mounts appearing inside the root do not
|
|
38
|
+
propagate back to the host, and unmounting it afterwards cannot take the
|
|
39
|
+
host's `/dev` with it.
|
|
40
|
+
|
|
41
|
+
## Options
|
|
42
|
+
|
|
43
|
+
| Option | Meaning |
|
|
44
|
+
|---|---|
|
|
45
|
+
| `-n`, `--no-mount` | Do not mount anything: the behaviour of the traditional `chroot`. Note that Bun itself cannot start without `/proc` and `/dev/urandom`, so `-n` suits statically linked programs. |
|
|
46
|
+
| `-k`, `--keep-mounts` | Leave the mounts in place after the command exits, to enter the same root again cheaply. Clean up later with `umount -R`. |
|
|
47
|
+
| `-v`, `--verbose` | Report every mount and unmount. |
|
|
48
|
+
| `--` | End of options; everything after it is NEWROOT and COMMAND. |
|
|
49
|
+
|
|
50
|
+
## Examples
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
# Mount a disk and enter the system on it
|
|
54
|
+
mount /dev/vda2 /mnt --mkdir
|
|
55
|
+
chroot /mnt
|
|
56
|
+
|
|
57
|
+
# Run one command and leave
|
|
58
|
+
chroot /mnt /bin/bun --version
|
|
59
|
+
|
|
60
|
+
# Watch what is set up and taken down
|
|
61
|
+
chroot -v /mnt /bin/sh -c 'ls /proc | head -3'
|
|
62
|
+
|
|
63
|
+
# Traditional behaviour: nothing is mounted for you
|
|
64
|
+
chroot -n /mnt /bin/sh
|
|
65
|
+
|
|
66
|
+
# Keep the mounts for repeated visits
|
|
67
|
+
chroot -k /mnt /bin/sh -c 'true'
|
|
68
|
+
chroot -k /mnt
|
|
69
|
+
umount -R /mnt
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Cleanup
|
|
73
|
+
|
|
74
|
+
When the command exits, every mount this invocation made is unmounted,
|
|
75
|
+
deepest first, including anything that appeared under the recursive `/dev`
|
|
76
|
+
bind. A mount that is still busy — a process left running inside, a shell
|
|
77
|
+
with its working directory there — is detached instead (`MNT_DETACH`), so
|
|
78
|
+
the kernel releases it once its last user goes away. The same cleanup runs
|
|
79
|
+
if `chroot(2)` itself fails or the command cannot be started, and on
|
|
80
|
+
`SIGTERM` or `SIGHUP`.
|
|
81
|
+
|
|
82
|
+
`Ctrl-C` goes to the command, not to `chroot`, so the mounts are still
|
|
83
|
+
removed after an interrupted program.
|
|
84
|
+
|
|
85
|
+
## Limits
|
|
86
|
+
|
|
87
|
+
- Needs to be superuser: `chroot(2)` requires `CAP_SYS_CHROOT`, and the
|
|
88
|
+
mounts require `CAP_SYS_ADMIN`. Buninu normally runs as root.
|
|
89
|
+
- The new root must contain the program you ask for and whatever it links
|
|
90
|
+
against; `chroot /mnt /bin/sh` fails with "not found" if `/mnt/bin/sh`
|
|
91
|
+
is not there.
|
|
92
|
+
- Only the filesystem view changes. Processes, network, users and the
|
|
93
|
+
hostname are shared with the host; this is not a container.
|
|
94
|
+
- `-k` leaves mounts behind on purpose. `umount -R NEWROOT` removes them.
|
|
95
|
+
|
|
96
|
+
## Exit status
|
|
97
|
+
|
|
98
|
+
The command's own status, or `125` if `chroot` itself failed, `126` if the
|
|
99
|
+
command was found but could not be run, and `127` if it was not found.
|
|
100
|
+
|
|
101
|
+
## See also
|
|
102
|
+
|
|
103
|
+
- Source: `/bin/chroot`
|
|
104
|
+
- `mount --help`, `umount --help`
|
|
105
|
+
- Shared native binding: `/lib/dlopen.js`
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# fbdev — draw directly on the Linux framebuffer
|
|
2
|
+
|
|
3
|
+
`/lib/fbdev.js` is both an importable drawing module and a small executable
|
|
4
|
+
demo. It uses `/dev/fb0`, framebuffer ioctls, a shared `mmap`, and `KDSETMODE`
|
|
5
|
+
through Bun FFI; it does not require X11, Wayland, SDL, or a window manager.
|
|
6
|
+
|
|
7
|
+
## Demo
|
|
8
|
+
|
|
9
|
+
Run it on Buninu's physical Linux console:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
bun /lib/fbdev.js
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The demo switches the active console to graphics mode, clears the framebuffer,
|
|
16
|
+
draws a cyan triangle, and waits. Press any key to restore text mode and exit.
|
|
17
|
+
Ordinary failures, direct process exit, `SIGHUP`, `SIGINT`, `SIGQUIT`, and
|
|
18
|
+
`SIGTERM` also restore the prior keyboard raw state and attempt to return the
|
|
19
|
+
console to text mode.
|
|
20
|
+
|
|
21
|
+
Each repeatable `-p`/`--points` supplies one polygon as x,y coordinate pairs:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
bun /lib/fbdev.js -p '100,50 40,250 300,250'
|
|
25
|
+
bun /lib/fbdev.js \
|
|
26
|
+
-p '100,50 40,250 300,250' \
|
|
27
|
+
-p '400,80 350,220 450,220'
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Every occurrence draws a separate filled polygon. Comma and whitespace
|
|
31
|
+
separators may be mixed inside its quoted value; the clearest form uses a
|
|
32
|
+
comma within each `x,y` point and spaces between points. If one polygon
|
|
33
|
+
contains an odd number of numeric values, its final unpaired value is ignored.
|
|
34
|
+
A `-p` containing only one number is therefore ignored as a whole. Each
|
|
35
|
+
non-empty polygon needs at least three complete points; more than three points
|
|
36
|
+
remain one polygon rather than starting another. If no drawable `-p` remains,
|
|
37
|
+
the demo draws its default triangle.
|
|
38
|
+
|
|
39
|
+
## JavaScript API
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
import {
|
|
43
|
+
openFramebuffer,
|
|
44
|
+
clear,
|
|
45
|
+
drawPoint,
|
|
46
|
+
drawLine,
|
|
47
|
+
drawLines,
|
|
48
|
+
fillPolygon,
|
|
49
|
+
flush,
|
|
50
|
+
} from "/lib/fbdev.js";
|
|
51
|
+
|
|
52
|
+
const display = openFramebuffer();
|
|
53
|
+
try {
|
|
54
|
+
clear(display);
|
|
55
|
+
fillPolygon(display, [[100, 50], [40, 250], [300, 250]], {
|
|
56
|
+
r: 64, g: 200, b: 255, a: 255,
|
|
57
|
+
});
|
|
58
|
+
drawLine(display, 0, 0, display.width - 1, display.height - 1, {
|
|
59
|
+
r: 255, g: 255, b: 255,
|
|
60
|
+
});
|
|
61
|
+
flush(display);
|
|
62
|
+
} finally {
|
|
63
|
+
display.close();
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The API uses short drawing names because it operates on a framebuffer rather
|
|
68
|
+
than an X11 `Display`. Colours are `{ r, g, b, a }` objects.
|
|
69
|
+
|
|
70
|
+
### Export reference
|
|
71
|
+
|
|
72
|
+
| Export | Purpose |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| `Framebuffer`, `openFramebuffer(path?)` | Open and describe a packed-pixel framebuffer. |
|
|
75
|
+
| `normalizePoints(values)` | Accept flat numbers, `[x,y]` arrays, or `{x,y}` objects. An unpaired flat value is ignored. |
|
|
76
|
+
| `parsePoints(strings)` | Parse comma/whitespace-separated CLI-style coordinates. |
|
|
77
|
+
| `drawPoint(display, x, y, color?)` | Draw one clipped pixel. |
|
|
78
|
+
| `drawLine(display, x1, y1, x2, y2, color?)` | Draw a clipped Bresenham line. |
|
|
79
|
+
| `drawLines(display, points, color?, close?)` | Join a sequence of points. |
|
|
80
|
+
| `fillPolygon(display, points, color?)` | Fill a polygon with the even-odd scanline rule. |
|
|
81
|
+
| `clear(display, color?)` | Fill the in-memory frame, black by default. |
|
|
82
|
+
| `flush(display)` | Copy the in-memory frame to the shared `/dev/fb0` mapping and synchronize it. |
|
|
83
|
+
| `blitImageData(display, imageData, x?, y?)` | Copy an RGBA `ImageData` (for example from CanvasKit's HTML canvas emulation) into the frame, converting to the framebuffer's format and clipping. |
|
|
84
|
+
| `openConsole`, `setConsoleGraphics`, `setConsoleText` | Explicit Linux virtual-console control for callers that need it. |
|
|
85
|
+
| `activeConsole(console)`, `activateConsole(console, n)`, `consoleNumber(path)` | `VT_GETSTATE` / `VT_ACTIVATE` + `VT_WAITACTIVE`, and the number in a `/dev/ttyN` path. |
|
|
86
|
+
| `watchConsoleSwitches(console, onAcquire)` | `VT_SETMODE` with `VT_PROCESS`: answers the kernel's switch-away and switch-back signals and calls `onAcquire` when the display returns. Returns a function restoring automatic switching. |
|
|
87
|
+
| `runGraphics(draw, { device, console, switchConsole }?)` | Open the framebuffer, put the console in graphics mode, run `await draw(display, { console, onRestore, onAcquire })`, and restore text mode however the call ends (return, throw, `process.exit()`, `SIGHUP`/`SIGINT`/`SIGQUIT`/`SIGTERM`). `console` lists console devices to try, such as `["/dev/tty1"]`; when the one opened is a `/dev/ttyN` other than the console on screen, the display is switched to it first and back afterwards (`switchConsole: false` disables this). Console switches with Ctrl-Alt-Fn keep working; `onAcquire(callback)` runs when the display comes back so the caller can repaint, and `onRestore(callback)` registers cleanup to run before text mode returns. |
|
|
88
|
+
| `runDemo({ polygons, device }?)` | Run the CLI demo through `runGraphics()`. Each item in `polygons` is drawn separately. |
|
|
89
|
+
|
|
90
|
+
The module supports 16-, 24-, and 32-bit packed-pixel framebuffers and uses
|
|
91
|
+
the kernel-reported stride, offsets, and RGB bitfields. Paletted and unusual
|
|
92
|
+
non-packed framebuffer formats are rejected rather than drawn incorrectly.
|
|
93
|
+
|
|
94
|
+
## Operational limits
|
|
95
|
+
|
|
96
|
+
- Run the demo from a real Linux virtual console. A PTY, serial console, SSH
|
|
97
|
+
session, or terminal pane cannot accept `KDSETMODE`.
|
|
98
|
+
- The framebuffer device and active virtual console must be accessible to the
|
|
99
|
+
process; Buninu normally runs as root.
|
|
100
|
+
- Imported drawing calls modify an in-memory frame until `flush()` is called.
|
|
101
|
+
- Importing the module does not switch console mode. Only `runDemo()` or an
|
|
102
|
+
explicit `setConsoleGraphics()` call does so.
|
|
103
|
+
- No userspace cleanup can run after `SIGKILL`, a kernel panic, power loss, or
|
|
104
|
+
a native runtime crash. If one leaves the virtual console in graphics mode,
|
|
105
|
+
switch to another VT or reboot to recover it.
|
|
106
|
+
|
|
107
|
+
## See also
|
|
108
|
+
|
|
109
|
+
- Source: `/lib/fbdev.js`
|
|
110
|
+
- Shared native binding: `/lib/dlopen.js`
|
|
111
|
+
- Skia on this framebuffer: `/lib/canvas.js` (`canvas.md`); the terminal
|
|
112
|
+
built on both: `bunterm`
|
|
113
|
+
- Linux UAPI: `linux/fb.h` and `linux/kd.h`
|
|
@@ -27,7 +27,7 @@ Use `-` as ARCHIVE to read from standard input or write to standard output.
|
|
|
27
27
|
| `-C DIR`, `--directory=DIR` | Read input files from DIR, or extract into DIR. |
|
|
28
28
|
| `-z`, `--gzip` | Create gzip-compressed tar, or explicitly identify gzip input. |
|
|
29
29
|
| `--zstd` | Create or read a zstd-compressed tar. A `.zst` or `.tzst` input is also detected by name. |
|
|
30
|
-
| `-v` | Print names while creating/extracting; with `-t`, also show each
|
|
30
|
+
| `-v` | Print names while creating/extracting; with `-t`, also show each member's size, modification time, kind and link target. |
|
|
31
31
|
|
|
32
32
|
Short options can be combined, for example `-xzvf` or `-czf`.
|
|
33
33
|
For the traditional first option word, the leading hyphen is optional, so
|
|
@@ -42,8 +42,34 @@ tar -xzf source.tar.gz -C /tmp/source
|
|
|
42
42
|
tar -tf source.tar.gz
|
|
43
43
|
tar --zstd -cf backup.tar.zst home
|
|
44
44
|
tar --zstd -xf backup.tar.zst -C /mnt/restore
|
|
45
|
+
|
|
46
|
+
# An Alpine root filesystem, symbolic links and all; then enter it
|
|
47
|
+
tar -xzf alpine-minirootfs-3.24.1-x86_64.tar.gz -C /mnt/alpine
|
|
48
|
+
chroot /mnt/alpine
|
|
45
49
|
```
|
|
46
50
|
|
|
51
|
+
## Links
|
|
52
|
+
|
|
53
|
+
Extraction restores symbolic links exactly as the archive records them,
|
|
54
|
+
including absolute targets such as `/bin/busybox` and targets that do not
|
|
55
|
+
exist yet, and it restores hard links. This is what GNU tar does, and it is
|
|
56
|
+
what an unpacked root filesystem needs: an Alpine minirootfs is 335 symbolic
|
|
57
|
+
links, 306 of them absolute, and without them the result has no `/bin/sh`.
|
|
58
|
+
|
|
59
|
+
`Bun.Archive` creates only the symbolic links whose target is relative and
|
|
60
|
+
stays inside the extraction directory, and skips hard links entirely, so
|
|
61
|
+
this command reads the archive's own headers (ustar, GNU `L`/`K` long names,
|
|
62
|
+
pax `x` records) and creates the rest itself once every file is in place.
|
|
63
|
+
Nothing is ever written through a link, because the links are made last.
|
|
64
|
+
|
|
65
|
+
A member's own name still follows GNU tar's rule: a leading `/` is dropped
|
|
66
|
+
and a name containing `..` is refused, so an archive cannot write outside
|
|
67
|
+
the extraction directory.
|
|
68
|
+
|
|
69
|
+
The same header scan backs listing, so `-t` reports every member —
|
|
70
|
+
directories, links, devices — and not just regular files. A symbolic link
|
|
71
|
+
shows its target, a hard link the file it points at.
|
|
72
|
+
|
|
47
73
|
## Current Bun.Archive limits
|
|
48
74
|
|
|
49
75
|
Creation stores regular files only. Symbolic links are rejected rather than
|
|
@@ -51,11 +77,9 @@ silently archived as the wrong type; modes, ownership, hard links, and empty
|
|
|
51
77
|
directories are not preserved. Bun 1.4.3 also requires file contents to be
|
|
52
78
|
materialized in memory before archive creation.
|
|
53
79
|
|
|
54
|
-
Extraction
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
but not the unavailable mode or owner. Bun provides gzip and zstd codecs but no xz or bzip2 codec,
|
|
58
|
-
so this command does not accept `.tar.xz` or `.tar.bz2`.
|
|
80
|
+
Extraction does not restore modes, ownership or timestamps. Bun provides gzip
|
|
81
|
+
and zstd codecs but no xz or bzip2 codec, so this command does not accept
|
|
82
|
+
`.tar.xz` or `.tar.bz2`.
|
|
59
83
|
|
|
60
84
|
Appending with `-r`/`rvf` is not supported. `Bun.Archive` has no append API;
|
|
61
85
|
rebuilding an existing archive through `Archive.files()` would silently lose
|
|
Binary file
|
|
Binary file
|