Files
isocreator/ts/classes/iso-packer.ts

124 lines
3.0 KiB
TypeScript

/**
* ISO Packer
* Repacks a directory into a bootable ISO using xorriso
*/
import { log } from '../logging.ts';
export class IsoPacker {
/**
* Pack a directory into an ISO
*/
async pack(sourceDir: string, outputIso: string, volumeLabel?: string): Promise<void> {
log.info(`Creating ISO from ${sourceDir}...`);
const label = volumeLabel || 'UBUNTU_CUSTOM';
// Use xorriso to create a bootable ISO
const command = new Deno.Command('xorriso', {
args: [
'-as',
'mkisofs',
'-r',
'-V',
label,
'-o',
outputIso,
'-J',
'-joliet-long',
'-cache-inodes',
'-isohybrid-mbr',
'/usr/lib/ISOLINUX/isohdpfx.bin',
'-b',
'isolinux/isolinux.bin',
'-c',
'isolinux/boot.cat',
'-boot-load-size',
'4',
'-boot-info-table',
'-no-emul-boot',
'-eltorito-alt-boot',
'-e',
'boot/grub/efi.img',
'-no-emul-boot',
'-isohybrid-gpt-basdat',
sourceDir,
],
stdout: 'piped',
stderr: 'piped',
});
const process = command.spawn();
const { code, stderr } = await process.output();
if (code !== 0) {
const errorText = new TextDecoder().decode(stderr);
throw new Error(`Failed to create ISO: ${errorText}`);
}
log.success(`ISO created successfully at ${outputIso}`);
// Make it hybrid bootable (USB compatible)
await this.makeIsohybrid(outputIso);
}
/**
* Make the ISO hybrid bootable (USB-compatible)
*/
private async makeIsohybrid(isoPath: string): Promise<void> {
try {
log.info('Making ISO hybrid bootable...');
const command = new Deno.Command('isohybrid', {
args: ['--uefi', isoPath],
stdout: 'piped',
stderr: 'piped',
});
const { code } = await command.output();
if (code === 0) {
log.success('ISO is now USB-bootable');
} else {
log.warn('isohybrid failed, ISO may not be USB-bootable');
}
} catch (err: unknown) {
const errorMessage = err instanceof Error ? err.message : String(err);
log.warn(`isohybrid not available: ${errorMessage}`);
}
}
/**
* Check if required tools are installed
*/
async checkDependencies(): Promise<boolean> {
try {
const xorrisoCmd = new Deno.Command('xorriso', {
args: ['--version'],
stdout: 'null',
stderr: 'null',
});
const { code } = await xorrisoCmd.output();
return code === 0;
} catch {
return false;
}
}
/**
* Ensure dependencies are installed
*/
async ensureDependencies(): Promise<void> {
const hasXorriso = await this.checkDependencies();
if (!hasXorriso) {
log.error('xorriso is not installed!');
log.info('Install xorriso:');
log.info(' Ubuntu/Debian: sudo apt install xorriso syslinux-utils');
log.info(' macOS: brew install xorriso syslinux');
throw new Error('Missing dependency: xorriso');
}
}
}