#!/usr/bin/perl -w
#
# (c) Bernhard Walle <bwalle@suse.de>
#
# 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; You may only use version 2 of the License, you have no option to
# use any other 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., 675 Mass
# Ave, Cambridge, MA 02139, USA.
#

use Getopt::Long;

my $VERSION = "0.3.3";
my $BLOCKSIZE = 1024;
my $PROGRESS_INTERVAL = 1; # seconds
my $PROGRESS_LOOPS = 50;

###############################################################################
# Outputs usage information
sub usage
{
    print "kdump-cat_progress $VERSION\n";
    print "";
    print "Syntax:\n";
    print "    kdump-cat_progress [-l length] SOURCE\n";
    print "\n";
    print "Options:\n";
    print "    -l length      Length in bytes of the stuff to copy\n";
}

###############################################################################
# Converts the size to mega bytes
sub to_mb
{
    my $size = shift;
    return $size / 1024.0 / 1024.0;
}

###############################################################################
# Shows the progress bar.
sub show_progress
{
    my $size = shift;
    my $current_size = shift;
    my $percentage = $current_size / $size;
    my $width = 40;
    my $oldflush = $|;

    $| = 1;

    my $stars = $percentage * $width;
    my $equals = $width - $stars;

    print STDERR "|";
    print STDERR "#" x $stars;
    print STDERR "-" x $equals;
    print STDERR "|  ";
    printf STDERR "%6d MB of %d MB (%2.1f%%)    \r", to_mb($current_size),
        to_mb($size), $percentage * 100;

    $| = $oldflush;
}

###############################################################################
# The main program

#
# parse command line
our ($print_help, $length);
GetOptions (
    'h|help' 				=> 	\$print_help,
    'l|length=s'			=>	\$length,
);
my $SOURCE = $ARGV[0];

if ($print_help) {
    usage();
    exit 0;
}

if (!$SOURCE) {
    usage();
    exit 1;
}

#
# get the size of the source
my $src_size;

if (defined $length) {
    $src_size = $length;
} else {
    ($src_size) = (stat($SOURCE))[7];
    if (!$src_size || $src_size <= 0) {
        print "Source file is empty\n";
        exit 1;
    }
}

open FH, $SOURCE or die "Could not open $SOURCE: $!\n";

my $read_bytes;
my $bytes;
my $total_read = 0;
my $lastprogress = time() - $PROGRESS_INTERVAL;
my $total_to_read = $src_size;
my $to_read = ($src_size < $BLOCKSIZE) ? $src_size : $BLOCKSIZE;
my $progress = 0;


while (($read_bytes = sysread(FH, $bytes, $to_read)) > 0) {

    syswrite(STDOUT, $bytes, $read_bytes);

    if (($lastprogress + $PROGRESS_INTERVAL) < time()) {
        show_progress($src_size, $total_read);
        $lastprogress = time();
    }

    $total_read += $read_bytes;
    $total_to_read -= $read_bytes;

    if ($to_read > $total_to_read) {
        $to_read = $total_to_read;
    }

    if ($progress % $PROGRESS_LOOPS == 0) {
        if ($total_to_read < $BLOCKSIZE) {
            $to_read = $total_to_read;
        }
    }

    $progress++;
}

show_progress($src_size, $src_size);

if ($read_bytes < 0) {
    die "Could not read: $!\n";
}

print STDERR "\n";

close FH;

# vim: set sw=4 ts=4 et:
