Files
appsandbox/tools/iso-patch/engine/ext4.h
T
James Stringer 2135f5cbeb Direct Ubuntu ISO->VHDX build (no subiquity, no cidata)
iso-patch.exe gains a new --ubuntu-to-vhdx mode that produces a fully
installed, bootable Ubuntu VHDX in one shot:
  - vendored xz-embedded + custom ext4 writer + squashfs reader
  - mounts the ISO, partitions GPT (ESP + Linux root), streams
    casper/minimal.squashfs into a freshly-built ext4 rootfs through
    a producer/N-decompress-worker/single-writer pipeline
  - installs signed shim + grub from the ISO's pool .debs onto ESP,
    writes a redirect grub.cfg pointing at the rootfs by UUID
  - plants a defensive one-shot first-boot systemd unit that runs
    grub-install + update-grub + AppSandbox guest setup (agent ELFs,
    kernel modules, systemd units, wsl-mesa, wsl-deps, ldconfig,
    no-sleep dconf, etc.) and reboots

linux_create_thread now spawns iso-patch with --ubuntu-to-vhdx
and a --stage manifest covering the full extras tree (reuses
stage_linux_agent_and_extras to populate a staging dir then walks
it). image_path is cleared post-build so the ISO isn't re-attached
to the runtime VM. ComPorts/com1 named pipe and the do_connect_rdp
window path are dropped (IDD is the only live display path now).

VideoMonitor stays unconditional (vmwp.exe crashes 0xC0000005
without it) — but with no ConnectionOptions/named pipe, matching
master.

JS frontend: "Installing Linux" branch added so the spinner label
no longer says "Installing Windows" for Linux VMs. Progress %
now tracks ingest fraction (n_processed / total_inodes) mapped
into 10..75%, with post-ingest phases at 82..99%.
2026-05-25 22:34:57 -04:00

76 lines
3.5 KiB
C

/* ext4.h - minimal ext4 image writer.
*
* Feature subset (deliberately small):
* INCOMPAT : FILETYPE | EXTENTS
* RO_COMPAT : SPARSE_SUPER | LARGE_FILE | HUGE_FILE | DIR_NLINK | EXTRA_ISIZE
* No journal, no metadata_csum, no xattrs, no flex_bg, no 64bit, no HTREE.
*
* Layout:
* block_size = 4096
* inode_size = 256
* blocks_per_group = 32768 (128 MiB per group)
* inodes_per_group = 1024 (per-group default; total inodes = groups * 1024)
*
* The writer is two-phase from the caller's perspective:
* 1. ext4_writer_open(): allocates layout, opens the phys disk, NO I/O yet
* 2. ext4_writer_add_*(): each call buffers an entry into a per-dir tree
* and (for regular files) allocates + writes data blocks immediately
* 3. ext4_writer_close(): writes superblocks, GDT, bitmaps, inode tables,
* and directory data blocks. All in one pass at close time.
*
* Memory: roughly 100 B/entry held in memory until close. ~5 MB for 52k.
*/
#ifndef POC_EXT4_H
#define POC_EXT4_H
#include <windows.h>
#include <stdint.h>
typedef struct ext4_writer ext4_writer_t;
/* Open a writer over [partition_lba_start, partition_lba_start+partition_lba_count)
* on the given physical disk handle. Layout is computed but no I/O happens.
* est_inodes is rounded up to a multiple of inodes_per_group. */
ext4_writer_t *ext4_writer_open(HANDLE phys,
uint64_t partition_lba_start,
uint64_t partition_lba_count,
uint32_t est_inodes);
/* Set the filesystem label (max 16 chars, copied). NULL for no label. */
void ext4_writer_set_label(ext4_writer_t *w, const char *label);
/* Add entries. Paths must be absolute (start with /). For a file, data may
* be NULL iff size is 0. Symlink target is NOT null-terminated; pass length. */
int ext4_writer_add_dir(ext4_writer_t *w, const char *path,
uint16_t perms, uint32_t uid, uint32_t gid,
uint32_t mtime);
int ext4_writer_add_file(ext4_writer_t *w, const char *path,
uint16_t perms, uint32_t uid, uint32_t gid,
uint32_t mtime, const void *data, uint64_t size);
int ext4_writer_add_symlink(ext4_writer_t *w, const char *path,
const char *target, size_t target_len,
uint32_t uid, uint32_t gid, uint32_t mtime);
int ext4_writer_add_special(ext4_writer_t *w, const char *path,
uint16_t mode_with_type,
uint32_t uid, uint32_t gid, uint32_t mtime,
uint32_t rdev);
/* Finalize: write superblocks, GDT backups, bitmaps, inode tables, and
* directory data blocks. Returns 0 on success. */
int ext4_writer_close(ext4_writer_t *w);
/* Convenience: return the root partition's UUID once layout is decided.
* Caller buffer must be >= 37 bytes (36 + null) for canonical text form. */
void ext4_writer_get_uuid_text(const ext4_writer_t *w, char *out, size_t cap);
/* Profiling: total bytes pushed into / flushed out of the coalescer,
* and total elapsed perf-counter ticks spent in WriteFile, plus syscall
* count. Useful for "where did the time go" reports. */
void ext4_writer_get_io_stats(const ext4_writer_t *w,
uint64_t *out_bytes_in,
uint64_t *out_bytes_flushed,
uint64_t *out_flush_ticks,
uint64_t *out_flush_calls);
#endif