Package: fdutils
Version: 5.4-20040228-1
Severity: wishlist
Tags: patch

The following script offers a friendly interface (pv on commandline,
dialog, or zenity for gui) for writing floppy disk images.  This
script doesn't just blast out the image and hope it's okay; unless you
specify otherwise, the script will verify (using cmp) that the image
can be read back and, if not, will reformat the floppy and try again
(exactly once).  I did this after far too many bad floppies (a
combination of flaky drives and the fact that floppy quality is
absolutely horrible these days).

If called without a disk image to write it will use a file chooser to
let the user browse to the file to write.  I hope to do an update-menu
thing that calls 'fburn --gui', which makes for a somewhat friendly
interface from a window manager menu or icon.  

If possible I'd like to be forwarded any bugs in the script so that I
can fix them, rather than you having to spend time on them.

It depends on bash, getopt, dd, cmp, superformat, pv, tee,
dialog, and zenity which on debian are provided by bash, util-linux, 
coreutils, diff, fdutils, pv, dialog, and zenity, although dialog and 
zenity are optional (though the default ui would have to changed to
commandline using pv instead of dialog, if dialog and zenity were to
be suggests or recommends).

#!/bin/bash 
# fburn 1.2 is used to write raw data (usually a floppy image) to a
# floppy.  

# Copyright (C) 2006 Daniel Dickinson <[EMAIL PROTECTED]>
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

display_usage () {
    echo ""
    echo "fburn 1.1 Copyright (C) 2006 Daniel Dickinson <[EMAIL PROTECTED]>"
    echo ""
    echo "fburn is used to write raw data (usually a floppy image) to a floppy."
    echo "  its default action is the write the image to floppy, then compare"
    echo "  the floppy to the image.  If there is an error during the compare"
    echo "  stage, fburn will make at reformatting the floppy and rewriting."
    echo ""
    echo "Usage: fburn [options] [image-to-write]"
    echo ""
    echo "   -a|--abort-on-failure      Don't try formatting then rewriting the"
    echo "                              image after a fail in compare or copy"
    echo ""
    echo "   -d|--debug                 Display debugging information"
    echo ""
    echo "   -f device|--device device  Floppy device name"
    echo ""
    echo "   -g|--gui                   Display progress bars, info boxes, and"
    echo "                              error messages as GUI dialogs"
    echo "   -h|--help                  This text"
    echo ""
    echo "   -i|--initial-format        Format before writing image, instead"
    echo "                              only after failing to write"
    echo "   -n|--no-dialogs            Display and prompt on command-line"
    echo "                             (no popup dialogs)"
    echo ""
    echo "image-to-write can be any file small enough to fit on a floppy"
    echo "  though usually it will be a floppy image.  If no image is"
    echo "  specified a file browser is opened."
    echo ""
}

#
# Q: Why do the copy and compare functions use fillstr and write fake data to
#    the pipe?
#
# A: We pad the output of cat (piped to pv) because dialog and zenity progress
# bars require that only the very last byte result in a progress report of 100%
# but pv rounds up so in many cases dialog and zenity think the job is done and
# terminating, breaking the pipe.  Also, because of floppy buffering, pv
# reports 100% when the last byte is written to the disk buffer, not when the 
# buffer is emptied.  By appending fake data (which never goes to disk) that
# doesn't make it to dialog or zenity until the disk buffer is empty, we see a
# mostly complete write, instead of no more dialog or zenity progress bar until
# the buffer unblocks.  This does throw off the math slightly, but I don't
# think that should be an issue since a progress bar really only gives a
# general feel for the progress made so far anyway.
#



##################
# Exit Codes
#################

OK=0
CANCEL=1

ERR_IMAGE=2
ERR_GETOPT=3
ERR_COPYTMP=4
ERR_COPYABORT=5
ERR_CMPTMP=6
ERR_CMPABORT=7
ERR_FORMATTMP=8
ERR_FLOPPYDEVW=9
ERR_FLOPPYDEVR=10
ERR_INITFORMAT=11
ERR_REFORMAT=12
ERR_INITDD=13

#####################
#
# Other constants
#
#####################

BLOCKSIZE=512

###############################
#
# Default settings for options
# false, true
#
###############################

INITIALFORMAT=false
DEBUG=false
GUI=false
FLOPPYDEV=/dev/fd0
ABORT=false
NODIALOG=false
SKIPLICENSE=false

################################
#
# Parse command line options
#
################################

CMDLINE=$(getopt --long 
device:,gui,initial-format,abort-on-failure,debug,no-dialogs,skip-license,help 
-o f:giadnsh -- "$@")

IMAGE=""

if [ $? != 0 ]; then
    echo "Error parsing options; Terminating." >&2 ; exit $ERR_GETOPT
fi

eval set -- "$CMDLINE"

while true; do
    case "$1" in
        -f|--device)
            FLOPPYDEV=$2
            shift 2
            ;;
        -g|--gui)
            GUI=true
            shift
            ;;
        -i|--initial-format)
            INITIALFORMAT=true
            shift
            ;;
        -a|--abort-on-failure)
            ABORT=true
            shift
            ;;
        -d|--debug)
            DEBUG=true
            shift
            ;;
        -n|--no-dialogs)
            NODIALOG=true
            shift
            ;;
        -s|--skip-license)
            SKIPLICENSE=true
            shift
            ;;
        -h|--help)
            display_usage
            exit 0
            ;;
        --)
            shift
            break
            ;;
        *)
            display_usage
            exit 2
            ;;
    esac
done

for arg do IMAGE="$arg"; break; done

if [ "$DEBUG" = "true" ]; then
    echo "'$IMAGE'"
fi

msgbox () {
    local CANCELLED
    CANCELLED=false

    if [ "$NODIALOG" = "true" ]; then
        echo "$1"
    elif [ "$GUI" = "true" ]; then
        zenity $2 --text="$1"
        if [ "$?" = "1" ]; then
            CANCELLED=true
        fi
    else
        dialog --clear
        dialog --msgbox "$1" 10 70
        if [ "$?" = "1" ]; then
            CANCELLED=true
        fi
    fi
    if [ "$CANCELLED" = "true" ]; then
        exit CANCEL
    fi
}

errbox () {
    msgbox "$1" "--error"
}

infobox () {
    msgbox "$1" "--info"
}

progressbar () {

    if [ "$GUI" = "true" ]; then
        zenity --progress --text="$1" --auto-close 2>&1
    elif [ "$NODIALOG" = "false" ]; then
        dialog --clear
        dialog --guage "$1" 9 70 2>&1
    fi
}

copy_image () {
    local EXIT
    local TMPFILE
    local remainder
    local fullblocks
    local fillstr
    local fakerem
    local fakesize
    local fakeblkrem
    local fakefull
    local faketotal
    local fakebytes
    local fakeblkbytes
    local CANCELLED
    CANCELLED=false
    
     
    if [ "$DEBUG" = "true" ]; then
        echo "Copying image"
    fi

    TMPFILE=$(mktemp -t "exit_code.XXXXXX")
    if [ "$?" != "0" ]; then
        errbox "Error getting temporary filename for copy_image"
        exit $ERR_COPYTMP
    fi

    remainder=$(expr $SIZE % $BLOCKSIZE)
    fullblocks=$(expr $SIZE / $BLOCKSIZE)
    if [ $remainder -ne 0 ]; then
        fullblocks=$(expr $fullblocks + 1)
    fi     
    fakerem=$(expr $SIZE % 100)
    fakesize=$(expr $SIZE / 100 )       
    if [ $fakerem -ne 0 ]; then
        fakesize=$(expr $fakesize + 1)
    fi
    fakeblkrem=$(expr $fakesize % $BLOCKSIZE)
    fakefull=$(expr $fakesize / $BLOCKSIZE)
    if [ $fakeblkrem -ne 0 ]; then
        fakefull=$(expr $fakefull + 1)
    fi
    faketotal=$(expr $fakefull + $fullblocks)
    fakeblkbytes=$(expr $faketotal '*' $BLOCKSIZE)

    fakebytes=$(expr $fakeblkbytes - $SIZE)
    
    fillstr=$(yes . | tr -d \\\n | dd bs=1 count=$fakebytes 2>/dev/null)
    
    if [ "$DEBUG" = "true" ]; then
        echo "remainder: $remainder"
        echo "fullblocks: $fullblocks"
        echo "fakerem: $fakerem"
        echo "fakesize: $fakesize"
        echo "fakeblkrem: $fakeblkrem"
        echo "fakefull: $fakefull"
        echo "faketotal: $faketotal"
        echo "fakeblkbytes: $fakeblkbytes"
        echo "fakebytes: $fakebytes"
#       echo "fillstr\n$fillstr"
    fi

    if [ "$NODIALOG" = "true" ]; then
        echo "Copying image $1 to $FLOPPYDEV"

        ( cat $1; echo $fillstr ) | pv -W -s $fakeblkbytes -n 2>$TMPFILE | pv 
-W -p -e -b -s $fakeblkbytes | ( dd of=$FLOPPYDEV obs=$BLOCKSIZE ibs=1 
count=$SIZE; cat - >/dev/null )
    else        
        ( cat $1; echo $fillstr ) | pv -W -s $fakeblkbytes -n 2>$TMPFILE | ( pv 
-W -n -s $fakeblkbytes | ( dd of=$FLOPPYDEV obs=$BLOCKSIZE ibs=1 count=$SIZE ; 
cat - >/dev/null ) 2>/dev/null ) 2>&1 | progressbar "Copying image $1 to 
$FLOPPYDEV"
        if [ "$?" = "1" ]; then
            CANCELLED=true
            exit CANCEL
        fi
    fi

    EXIT=$(cat $TMPFILE | sed -e '/^[0-9][0-9]*$/!d' | tail -n 1 )

    if [ "$DEBUG" = "true" ]; then
        cat $TMPFILE
        echo "\$EXIT = $EXIT"
    fi    
    rm -f $TMPFILE
    
    if [ "$EXIT" != "100" ]; then
        if [ "$ABORT" = "true" ]; then
            errbox "Error writing image to floppy; aborting"
            exit $ERR_COPYABORT
        fi
        return 1
    else
        return 0
    fi
}

compare_image () {
    local EXIT
    local TMPFILE
    local fillstr
    local fakesize
    local fakerem
    local faketotal
    local CANCELLED
    CANCELLED=false

    if [ "$DEBUG" = "true" ]; then
        echo "Comparing image"
    fi

    TMPFILE=$(mktemp -t "exit_code.XXXXXX")
    if [ "$?" != "0" ]; then
        errbox "Error getting temporary filename for compare_image"
        exit $ERR_CMPTMP
    fi

    fakerem=$(expr $SIZE % 100)
    fakesize=$(expr $SIZE / 100 )       
    if [ $fakerem -ne 0 ]; then
        fakesize=$(expr $fakesize + 1)
    fi
    faketotal=$(expr $fakesize + $SIZE)
    fillstr=$(yes . | tr -d \\\n | dd count=$fakesize bs=1 2>/dev/null)

    if [ "$NODIALOG" = "true" ]; then
        echo "Comparing file $1 to $FLOPPYDEV"
        (cat $1 ; echo $fillstr ) | pv -W -n -s $faketotal 2>$TMPFILE | pv -W 
-e -b -p -s $faketotal | ( cmp -n $SIZE $FLOPPYDEV ; cat - >/dev/null)
    else
        (cat $1; echo $fillstr) | ( pv -W -n -s $faketotal | ( cmp -n $SIZE 
$FLOPPYDEV ; cat - >/dev/null ) ) 2>&1 | tee $TMPFILE | progressbar "Comparing 
file $1 to $FLOPPYDEV" 
        if [ "$?" = "1" ]; then
            CANCELLED=true
            exit CANCEL
        fi
    fi
    EXIT=$(cat $TMPFILE | sed -e '/^[0-9][0-9]*$/!d' | tail -n 1 )
    if [ "$DEBUG" = "true" ]; then
        cat $TMPFILE
        echo "\$EXIT = $EXIT"
    fi
    rm -f $TMPFILE

    if [ "$EXIT" != "100" ]; then
        if [ "$ABORT" = "true" ]; then
            errbox "Error comparing image to floppy; aborting"
            exit $ERR_CMPABORT
        fi
        return 1
    else
        return 0
    fi
}

copy_compare () {
    local DDOK
    local CMPOK
    
    CMPOK=false
    
    copy_image $1

    if [ "$?" = "0" ]; then
        DDOK=true
    else
        DDOK=false
    fi

    if [ "$DDOK" = "true" ]; then
        compare_image $1
        if [ "$?" = "0" ]; then
            CMPOK=true
        else
            CMPOK=false
        fi
    else
        if [ "$DEBUG" = "true" ]; then
            echo "Copy failed"
        fi
        return 1
    fi

    if [ "$DDOK" = "true" ] && [ "$CMPOK" = "true" ]; then
        return 0
    else
        if [ "$DEBUG" = "true" ]; then
            echo "Compare failed"
        fi
        return 1
    fi    
}

doformat () {
    local TMPFILE
    local EXIT

    TMPFILE=$(mktemp -t "exit_code.XXXXXX")

    if [ "$?" != "0" ]; then
        errbox "Error getting temporary filename for format"
        exit $ERR_FORMATTMP
    fi
    if [ "$NODIALOG" = "true" ]; then
        echo "Formatting floppy"
        ( superformat -v 2 --superverify $FLOPPYDEV | cat -A ; echo -n 
"........") | pv -n -s 650 2>$TMPFILE | pv -p -e -s 650 >/dev/null
    else
        ( superformat -v 2 --superverify $FLOPPYDEV | cat -A ; echo -n 
"........") | ( pv -n -s 650 >/dev/null ) 2>&1 | tee $TMPFILE | progressbar 
"Formatting floppy" 
    fi

    EXIT=$(cat $TMPFILE | sed -e '/^[0-9][0-9]*$/!d' | tail -n 1 )

    if [ "$DEBUG" = "true" ]; then
        cat $TMPFILE
        echo "\$EXIT = $EXIT"
    fi
    rm -f $TMPFILE

    if [ "$EXIT" = "100" ]; then
        return 0
    else
        return 1
    fi
}


###############################

# SCRIPT BODY

###############################

CANCELLED=false

if [ "$DEBUG" = "true" ]; then
    echo "Entering main body of fburn script"
fi

if [ "$NODIALOG" = "false" ] && [ "$GUI" = "false" ]; then
    dialog --clear
fi

if [ "$SKIPLICENSE" = "false" ]; then
    infobox "fburn 1.2, Copyright (C) 2006 Daniel Dickinson
fburn comes with ABSOLUTELY NO WARRANTY; This is free
software and you are welcome to redistribute it under certain
conditions; see the GNU Public License which you should have
received with this software.  If not, see 
http://www.gnu.org/licenses/gpl.html, or contact the author
by email at [EMAIL PROTECTED]"
fi

if [ -n $(echo "$IMAGE" | tr -d \  ) ]; then
    if [ ! -r "$IMAGE" ]; then
        if [ "$GUI" = "true" ]; then
            IMAGE=$(zenity --file-selection)
            if [ "$?" = "1" ]; then
                CANCELLED=true
            fi
        elif [ "$NODIALOG" = "false" ]; then
            IMAGE=$(dialog --clear --stdout --fselect "$(pwd)/*" 15 70 )
            if [ "$IMAGE" = "" ]; then
                CANCELLED=true
            fi
        fi
    elif [ "$DEBUG" = "true" ]; then
        echo "Image to write = $IMAGE"
    fi
fi

if [ "$CANCELLED" = "true" ]; then
    exit $CANCEL
fi

if [ -n $(echo "$IMAGE" | tr -d \  ) ]; then
    if [ ! -r "$IMAGE" ]; then
        errbox "Specified file '$IMAGE' is not readable"
        exit $ERR_IMAGE    
    elif [ "$DEBUG" = "true" ]; then
        echo "Image to write = $IMAGE"
    fi
fi

if [ ! -w "$FLOPPYDEV" ]; then
    errbox "Specified device for floppy ($FLOPPYDEV) is not writable"
    exit $ERR_FLOPPYDEVW
fi

if [ ! -r "$FLOPPYDEV" ]; then
    errbox "Specified device for floppy ($FLOPPYDEV) is not readable"
    exit $ERR_FLOPPYDEVR
fi

if [ "$INITIALFORMAT" = "true" ]; then
    doformat
    if [ "$?" != "0" ]; then
        errbox "Initial format failed"
        exit $ERR_INITFORMAT
    fi
fi    

SIZE=$(du -s -b $IMAGE | cut -f1)

if [ "$DEBUG" = "true" ]; then
    echo "Image size = $SIZE"
fi

copy_compare $IMAGE

if [ "$?" = "0" ]; then
    infobox "Image successfully written to $FLOPPYDEV"
    exit 0
elif [ "$INITIALFORMAT" = "false" ]; then
    doformat
    if [ $? != 0 ]; then
        errbox "Format after failed copy or compare also failed"
        exit $ERR_REFORMAT
    fi
else
    errbox "Writing or comparison of image failed after initial format"
    exit $ERR_INITDD
fi

copy_compare $IMAGE
            
if [ "$?" != "0" ]; then 
    errbox "Compare failed even after reformat"
else
    infobox "Compare initially failed, but succeeded after reformat"
fi



-- System Information: Debian Release: 3.1
  APT prefers testing
  APT policy: (200, 'testing'), (75, 'unstable'), (10, 'experimental')
Architecture: i386 (i686)
Kernel: Linux 2.6.16-2-k7
Locale: LANG=en_CA, LC_CTYPE=en_CA (charmap=ISO-8859-1)

Versions of packages fdutils depends on:
ii  debianutils                   2.8.4      Miscellaneous utilities specific t
ii  libc6                         2.3.6-15   GNU C Library: Shared libraries

-- no debconf information


-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to