From dc356f7ee8ba4ea084c79c9e6c4b4f7e335ff697 Mon Sep 17 00:00:00 2001 From: twojstaryzdomu Date: Sun, 5 Sep 2021 04:22:36 +0200 Subject: [PATCH] extfs/img: New file - support for MS-DOS disk images. --- misc/mc.ext.in | 4 ++ src/vfs/extfs/helpers/Makefile.am | 2 +- src/vfs/extfs/helpers/img | 94 +++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 1 deletion(-) create mode 100755 src/vfs/extfs/helpers/img diff --git a/misc/mc.ext.in b/misc/mc.ext.in index e821900b8f..d71b4fc518 100644 --- a/misc/mc.ext.in +++ b/misc/mc.ext.in @@ -288,6 +288,10 @@ shell/.deba Open=%cd %p/deba:// View=%view{ascii} @EXTHELPERSDIR@/package.sh view deba +# MS-DOS disk image +shell/i/.img + Open=%cd %p/img:// + # ISO9660 shell/i/.iso Open=%cd %p/iso9660:// diff --git a/src/vfs/extfs/helpers/Makefile.am b/src/vfs/extfs/helpers/Makefile.am index f1ea0acc32..e46f6068d6 100644 --- a/src/vfs/extfs/helpers/Makefile.am +++ b/src/vfs/extfs/helpers/Makefile.am @@ -4,7 +4,7 @@ extfsdir = $(libexecdir)/@PACKAGE@/extfs.d EXTFS_MISC = README README.extfs # Scripts hat don't need adaptation to the local system -EXTFS_CONST = bpp changesetfs gitfs+ patchsetfs rpm trpm u7z uc1541 +EXTFS_CONST = bpp changesetfs gitfs+ img patchsetfs rpm trpm u7z uc1541 # Scripts that need adaptation to the local system - source files EXTFS_IN = \ diff --git a/src/vfs/extfs/helpers/img b/src/vfs/extfs/helpers/img new file mode 100755 index 0000000000..6ea2de17ae --- /dev/null +++ b/src/vfs/extfs/helpers/img @@ -0,0 +1,94 @@ +#!/usr/bin/env perl +# VFS-wrapper for MS-DOS IMG files using mtools +# +# Written by twojstaryzdomu (twojstaryzdomu@users.noreply.github.com), 2021 +# + +my ( $cmd, $archive, @args ) = @ARGV; +die "$archive does not exist\n" unless -f "$archive"; +my $size_kb = ( -s $archive ) / 1024; +my $drive = 'b'; + +my $actions = { + list => "mdir -f -i \'$archive\'", + copyout => "mcopy -m -n -o -p -i \'$archive\'", + copyin => "mcopy -m -n -o -p -i \'$archive\'", + rm => "mdel -i \'$archive\'", + mkdir => "mmd -i \'$archive\'", + rmdir => "mrd -i \'$archive\'", + run => "dosbox -noautoexec -c \'IMGMOUNT -size $size_kb $drive: \'$archive\'\' -c '$drive:\' -c", + test => "logger \'$archive\'" +}; + +my $regex_list = qr"^(\S+)\s+(\S*)\s+(\S+)\s+(\d{4})-(\d{2})-(\d{2})\s+(\d{1,2}):(\d{1,2})(?:\s*)(\S+)*\s*$"; + +sub print_debug { + print "@_\n" if exists $ENV{DEBUG}; +} + +sub run_cmd { + my $cmd = shift; + my @output = ( do { open( my $line, "$cmd | " ) or die "$0: Can't run $cmd"; <$line>; } ); + print_debug "run_cmd $cmd"; + return \@output; +} + +sub check_mtools { + my $cmd = shift; + my ( $tool ) = $actions->{ $cmd } =~ /^(\w+)/; + foreach ( split( ":", $ENV{PATH} ) ) { + return 1 if -e "$_/$tool" + } + return; +} + +sub default_handler { + my ( $cmd, $archive, @args ) = ( @_ ); + print_debug "default_handler: @args"; + if ( $cmd eq 'copyin' ) { + if ( my ( $name, $ext ) = $args[0] =~ /(\w+)\.(\w+)$/ ) { + die "filename $name.$ext too long to copy to $archive\n" if ( length( $name ) > 8 || length( $ext ) > 3 ); + } + $args[0] = "::$args[0]"; + @args = reverse @args; + } + elsif ( $cmd eq 'copyout' ) { + $args[0] = "::$args[0]"; + } + my $output = run_cmd "$actions->{ $cmd } @args"; + if ( $cmd eq 'list' ) { + my $exec = check_mtools( run ) + ? 'rwxr-xr-x' + : 'rw-r--r--'; + foreach ( @{ $output } ) { + chomp; + next if /^$/; + if ( my ( $name, $ext, $size, $year, $mon, $day, $hours, $mins, $longname ) = $_ =~ /$regex_list/ ) { + print_debug "list: name = $name, ext = $ext, size = $size, year = $year, mon = $mon, day = $day, hours = $hours, mins = $mins, longname = $longname"; + next if ( $name eq '.' || $name eq '..' ); + my $perms = ( $size ne '' + ? '-' + : 'd' ) + . ( ( $ext eq 'exe' || $ext eq 'com' || $ext eq 'bat' ) + ? $exec + : 'rw-r--r--' ); + my $path = $longname + ? "$args[0]/$longname" + : uc( "$args[0]/$name" . ( $ext ? ".$ext" : "" ) ); + $secs = defined $secs ? $secs : "00"; + printf "%-10s 1 %-8d %-8d %8s %s/%s/%s %s:%s:%s %s", $perms, $<, + $(, $size ne '' ? $size : 0, $mon, $day, $year, $hours, $mins, $secs, $path + . "\n"; + default_handler( $cmd, $archive, $path ) if ( $size eq '' ); + } + else { + print_debug "list: skipped: $_"; + } + } + } +} + +print_debug "$0: cmd = $cmd; archive = $archive; args = @args"; +die "Cannot find command $cmd, are mtools installed?\n" unless check_mtools( $cmd ); +exists $actions->{ $cmd } ? default_handler( $cmd, $archive, @args ) + : die "mode $cmd not available\n";