#!/bin/bash set -euo pipefail # TODO: check with dash to confirm that it is working! # TODO: check dependencies like 7z/unzip/cabextract and generalize # TODO: deal with case-insenstivity on input! export LC_ALL=C script_name="$(basename $0)" cd_path='' fdimg_path='' cd_drv='' msg_help () { echo "Usage: $script_name -i -o [-c ] [-m ]" echo " needs to point to root of extracted/mounted ISO/CD" } msg_err () { echo "Error: $@" >&2 } 7z_e () { # Extract single file to empty dir, to aid with uppercase rename # $1 - path to archive, starting from CD root # $2 - path inside archive # $3 - path inside floppy (only if renaming) # For now assuming no subdirs in archives # TODO: auto-rename to uppercase if only 2 arguments! # TODO: automatically match case of file inside archive! # TODO: check if 7z actually extracted file if [ $# -gt 3 ] || [ $# -lt 2 ]; then msg_err "7z_e(): Invalid number of arguments" exit 1 fi # Make sure extract dir is empty extracted_cnt=$(ls -1 "$FDDIR/extract/" | wc -l) if [ "$extracted_cnt" != "0" ]; then msg_err "Unexpected $FDDIR/extract/ contents" exit 1 fi 7z -ssc- e "$cd_path/$1" "$2" -o"$FDDIR/extract/" > /dev/null # 7z doesn't seem to produce exit code on failure extracted_file=$(ls -1 "$FDDIR/extract/") if [ -z "$extracted_file" ] || [ ! -s "$FDDIR/extract/$extracted_file" ]; then msg_err "Failed to extract $2 from $1" exit 1 fi if [ $# -eq 3 ]; then mv "$FDDIR/extract/$extracted_file" "$FDDIR/$3" else extracted_upper=$(ls -1 "$FDDIR/extract/" | tr '[a-z]' '[A-Z]') mv "$FDDIR/extract/$extracted_file" "$FDDIR/$extracted_upper" fi } while getopts 'i:o:c:m:' copt do case $copt in i) cd_path="$OPTARG" ;; o) fdimg_path="$OPTARG" ;; c) cd_drv="$OPTARG" ;; ?) msg_help ;; esac done if [ -z "$cd_path" ] || [ -z "$fdimg_path" ]; then msg_err 'Missing path to cd or floppy image' msg_help exit 1 fi if [ ! -d "$cd_path" ]; then msg_err "Mounted/extracted CD/ISO directory $cd_path does not exist" msg_help exit 1 fi if [ ! -f "$cd_path/admin/nettools/fac/ltools.dta" ]; then msg_err "$cd_path does not contain windows 95 files or it's missing OPK portion" msg_help exit 1 fi if [ -e "$fdimg_path" ]; then msg_err "$fdimg_path already exists!" exit 1 fi # TODO: fdimg_path dir check FDDIR=$(mktemp -d) if [ $? != 0 ] || [ -z "$FDDIR" ] || [ ! -d "$FDDIR" ] || [ ! -w "$FDDIR" ]; then msg_err "failure to create tmpdir $FDDIR" exit 1 fi mkdir -p "$FDDIR/extract" echo "TMPDIR: $FDDIR" # Extract/rename/prepare files # Floppy bootsector # admin/nettools/fac/{tls,pld,ltools}.dta # TODO: have wrapper for 7z that will save 7z log to 7z.log and output it on errors 7z x "$cd_path/admin/nettools/fac/tls.dta" 'PBF.IMG' -o"$FDDIR" > /dev/null # Essential files 7z x "$cd_path/admin/nettools/fac/ltools.dta" 'io.sys' -o"$FDDIR" > /dev/null mv "$FDDIR/io.sys" "$FDDIR/IO.SYS" #7z x "$cd_path/admin/nettools/fac/ltools.dta" 'MSDOS.SYS' -o "$FDDIR" #7z x "$cd_path/admin/nettools/fac/pld.dta" 'MSDOS.FAC' -o "$FDDIR" #mv 'MSDOS.FAC' 'MSDOS.SYS' cat > "$FDDIR/MSDOS.SYS" << EOF [OPTIONS] BOOTGUI=0 LOGO=0 EOF 7z x "$cd_path/admin/nettools/fac/ltools.dta" 'command.com' -o"$FDDIR" > /dev/null mv "$FDDIR/command.com" "$FDDIR/COMMAND.COM" # Memory manager - TODO: conditional 7z x "$cd_path/admin/nettools/fac/ltools.dta" 'HIMEM.SYS' -o"$FDDIR" > /dev/null # CONFIG.SYS - TODO: conditional - also concatenate several things: # MCD if HIMEM # Add extra CD driver line if including CD driver # CD driver # Probably creates too much hardcode: # SHELL=A:\COMMAND.COM A:\ /P # Can we have relative path instead? cat > "$FDDIR/CONFIG.SYS" << EOF DEVICE=HIMEM.SYS /TESTMEM:OFF BUFFERS=20 FILES=60 LASTDRIVE=Z DOS=HIGH,UMB SHELL=A:\COMMAND.COM A:\ /P DEVICE=CDROM.SYS /D:MSCD000 EOF # TODO # MSCDEX.EXE 7z x "$cd_path/admin/nettools/fac/tls.dta" 'MSCDEX.EXE' -o"$FDDIR" > /dev/null # CD driver - for now OAK 7z x "$cd_path/drivers/modem/wdlboca1/drivers.zip" 'ATAPI_CD.SYS' -o"$FDDIR" > /dev/null mv "$FDDIR/ATAPI_CD.SYS" "$FDDIR/CDROM.SYS" # Autoexec for MSCDEX.EXE - based on AUTOEXEC.FAC TODO echo '@ECHO OFF' > "$FDDIR/AUTOEXEC.BAT" echo 'SET PATH=A:' >> "$FDDIR/AUTOEXEC.BAT" echo -ne 'LH MSCDEX.EXE /D:MSCD000 /L:Z' >> "$FDDIR/AUTOEXEC.BAT" # TOOLS 7z x "$cd_path/admin/nettools/fac/tls.dta" 'OXCOPY.EXE' -o"$FDDIR" > /dev/null mv "$FDDIR/OXCOPY.EXE" "$FDDIR/XCOPY.EXE" 7z x "$cd_path/admin/nettools/fac/pld.dta" 'OFORMAT.COM' -o"$FDDIR" > /dev/null mv "$FDDIR/OFORMAT.COM" "$FDDIR/FORMAT.COM" 7z x "$cd_path/admin/nettools/fac/pld.dta" 'ofdisk.exe' -o"$FDDIR" > /dev/null mv "$FDDIR/ofdisk.exe" "$FDDIR/FDISK.EXE" 7z x "$cd_path/admin/nettools/fac/ltools.dta" 'SYS.COM' -o"$FDDIR" > /dev/null 7z x "$cd_path/admin/nettools/fac/pld.dta" 'REBOOT.EXE' -o"$FDDIR" > /dev/null 7z x "$cd_path/admin/nettools/fac/cbs.dta" 'ATTRIB.EXE' -o"$FDDIR" > /dev/null 7z x "$cd_path/admin/nettools/fac/cbs.dta" 'EDIT.COM' -o"$FDDIR" > /dev/null cp "$cd_path/win95/scandisk.exe" "$FDDIR/SCANDISK.EXE" # Convert text files to dos newlines unix2dos -q "$FDDIR/MSDOS.SYS" unix2dos -q "$FDDIR/CONFIG.SYS" unix2dos -q "$FDDIR/AUTOEXEC.BAT" # Final floppy creation mkfs.msdos -C "$fdimg_path" 1440 dd if="$FDDIR/PBF.IMG" of="$fdimg_path" conv=notrunc status=none mcopy -i "$fdimg_path" "$FDDIR/IO.SYS" :: mcopy -i "$fdimg_path" "$FDDIR/MSDOS.SYS" :: mcopy -i "$fdimg_path" "$FDDIR/CONFIG.SYS" :: mcopy -i "$fdimg_path" "$FDDIR/HIMEM.SYS" :: mcopy -i "$fdimg_path" "$FDDIR/CDROM.SYS" :: mcopy -i "$fdimg_path" "$FDDIR/"*.COM :: mcopy -i "$fdimg_path" "$FDDIR/"*.EXE :: mcopy -i "$fdimg_path" "$FDDIR/"*.BAT :: # TODO: This does not fix OEMID mlabel -i test.img ::WIN_BOOT -n # TODO: cleanup #rm -vrd "$FDDIR" echo "Removed $FDDIR"