package PkgSize;

use strict;
use warnings;
use base 'Exporter';
use List::Util qw(sum);
use POSIX qw(floor);

our $VERSION   = 1.000_003;

my %name_lookup;
our $DPKG_DIR = '/var/lib/dpkg';
my $rootfsid;

sub read_names {
    my $pkg;

    open my $infile, '<', "$DPKG_DIR/status";
    while ( my $line = <$infile> ) {
        $line =~ s/[\r\n]+\z//smx;

        if ( $line =~ /\APackage:\s(.*)/smx ) {
            $pkg = $1;
        } elsif ( $line =~ /\AMaemo-Display-Name:\s(.*)/smx ) {
            $name_lookup{$pkg} = $1;
        }
    }
    close $infile;

    return;
}

sub get_name {
    my $pkg = shift;

    if ( defined $name_lookup{$pkg} ) {
        return $name_lookup{$pkg};
    }

    return;
}

sub disk_usage {
    my ($file, $seen) = @_;

    my @stat = stat $file;
    my $inode = $stat[1];

    return if ( $seen->{$inode}++ );

    my $blksize  = $stat[11];
    my $chunknum = $stat[12];
    my $blk_mult = $blksize / 512;

    my $blk_count = floor(($chunknum + $blk_mult - 1) / $blk_mult);

    return $blk_count * $blksize / 1024;
}

sub get_size {
    my ( $pkg, $list ) = @_;

    return if ( not defined $pkg );
    return if ( not -f "/var/lib/dpkg/info/$pkg.list" );

    my %dulist;
    my %seen;

    open my $infile, '<', "$DPKG_DIR/info/$pkg.list";
    while ( my $file = <$infile> ) {
        $file =~ s/[\r\n]+\z//smx;

        next if ( not -f $file );
        next if ( -l $file );
        next if ( not is_rootfs($file) );

        my $size = disk_usage($file, \%seen);
        next if ( not defined $size );
        next if ( $size == 0 );

        $dulist{$file} = $size;
    }
    close $infile;

    return if ( not %dulist );

    if ($list) {
        return %dulist;
    } else {
        return sum values %dulist;
    }
}

sub get_fsid {
    my $file = shift;

    my $id = (stat $file)[0];

    return $id;
}

sub is_rootfs {
    my $file = shift;

    if ( not defined $rootfsid ) {
        $rootfsid = get_fsid(q{/});
    }

    if ( get_fsid($file) == $rootfsid ) {
        return 1;
    }

    return 0;
}

1;

# vim: et ts=4
