#!/usr/bin/perl
#
# Copyright © 2015-2020 by Vincent Slyngstad
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE
# FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the names of the authors above
# shall not be used in advertising or otherwise to promote the sale, use
# or other dealings in this Software without prior written authorization
# from those authors.
#
# Given a set of directories, assemble a .xml
# file for those whose names make them eligible
# for inclusion in an OS/8 volume.
#
# For now, build a RK05/SerialDisk sized volume.
# Given a directory, are all the bits available
# to make it a system volume?
sub isSystem {
local($d) = $_[0];
# Every volume needs these, and we've no default boot loader.
die "$d/.boot" unless -f "$d/.boot" && (384 == -s "$d/.boot");
die "$d/.dir" unless -f "$d/.dir";
# Not a system volume unless .kmon exits.
return 0 unless -f "$d/.kmon" && (1536 == -s "$d/.kmon");
# Trying to be a system volume, check other requirements.
die "$d/.usr" unless -f "$d/.usr" && (1152 == -s "$d/.usr");
die "$d/.dhand" unless -f "$d/.dhand" && (3072 == -s "$d/.dhand");
die "$d/.end" unless -f "$d/.ent" && (384 == -s "$d/.ent");
die "$d/.sblks" unless -f "$d/.sblks" && (6912 == -s "$d/.sblks");
die "$d/.cdec" unless -f "$d/.cdec" && (1152 == -s "$d/.cdec");
die "$d/.sdate" unless -f "$d/.sdate" && (768 == -s "$d/.sdate");
die "$d/.merr" unless -f "$d/.merr" && (384 == -s "$d/.merr");
die "$d/.chain" unless -f "$d/.chain" && (384 == -s "$d/.chain");
die "$d/.sodt" unless -f "$d/.sodt" && (1536 == -s "$d/.sodt");
die "$d/.rsvd" unless -f "$d/.rsvd" && (384 == -s "$d/.rsvd");
die "$d/.cclr" unless -f "$d/.cclr" && (384 == -s "$d/.cclr");
die "$d/.td8e" unless -f "$d/.td8e" && (384 == -s "$d/.td8e");
return 1;
}
# Given a directory, make a sorted list of files
# suitable for inclusion.
sub getdir {
local(%dir) = ();
opendir(DIR, "$_[0]") || die "$_[0]: $!";
foreach $f (readdir(DIR)) {
$f =~ y/A-Z/a-z/;
next unless $f =~ /^[a-z0-9]{1,6}([.][a-z0-9]?[a-z0-9]?)?$/;
die "Upper/lower case collision on $_[0]/$f" if defined $dir{$f};
$dir{$f} = 1;
}
return sort keys %dir;
}
# Emit the .xml for the proposed directory.
sub copyout {
local($sblk, $d, @dir) = @_;
local($f, $size, $end);
foreach $f (@dir) {
# Figure out whether the extension indicates a binary.
# BUGBUG: These rules are different than ox8explode.
$ext = $f; $ext =~ s/^.*[.]//;
$mode = "text";
$mode = "binary" if $ext eq "sv";
$mode = "binary" if $ext eq "lo";
$mode = "binary" if $ext eq "hi";
$mode = "binary" if $ext eq "rl";
$mode = "binary" if $ext eq "bn";
# BUGBUG: Need case insensitive lookup!
$size = -s "$d/$f";
die "$d/$f not integer blocksize: $size\n" if ($mode eq "binary") && ($size % 384);
$size = int(($size + 383) / 384);
$end = $sblk + $size - 1;
die "Too many blocks for $d: $f" if $end >= $fsize;
printf XML "\n", $sblk, $end;
$sblk = $end + 1;
}
# Emit an empty for the remaining space, if any.
return if $sblk == $fsize;
$end = $fsize - 1;
printf XML "\n", $sblk, $end;
}
sub bplate {
local($d) = $_[0];
print XML "\n";
return unless $sysfs;
print XML "\n";
print XML "\n";
print XML "\n";
print XML "\n";
print XML "\n";
print XML "\n";
print XML "\n";
print XML "\n";
print XML "\n";
print XML "\n";
print XML "\n";
print XML "\n";
print XML "\n";
print XML "\n";
print XML "\n";
}
$fsize = 06260; $vsize = 014540; # Default to RK05
foreach $d (@ARGV) {
if ($d =~ /^-rk05/) {
$fsize = 06260;
$vsize = 014540;
next;
}
if ($d =~ /^-rx1/) {
$fsize = $vsize = 0756;
next;
}
if ($d =~ /^-rx2/) {
$fsize = $vsize = 01734;
next;
}
$f =~ s/.xml$//; $f =~ s/.[0-9]$//;
open(XML, ">$d.xml+") || die "$d.xml+: $!";
print XML "\n";
print XML "\n";
# BUGBUG: Should rather loop here.
$sysfs = &isSystem("$d.0");
@dir = &getdir("$d.0");
print XML "\n";
©out($sysfs? 070 : 07, "$d.0", @dir);
print XML "\n";
&bplate("$d.0");
print XML "\n";
if ($vsize > $fsize) {
print XML "\n";
$sysfs = &isSystem("$d.1");
@dir = &getdir("$d.1");
print XML "\n";
©out($sysfs? 070 : 07, "$d.1", @dir);
print XML "\n";
&bplate("$d.1");
print XML "\n";
}
print XML "\n";
}