From f1db30b2d69590bdbf8a7b07b634ce67ad479f6f Mon Sep 17 00:00:00 2001 From: Valko Laszlo Date: Mon, 15 Apr 2019 02:56:53 +0200 Subject: [PATCH] Implemented checking if extra driver is already installed. --- pkgtool.pm | 119 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 92 insertions(+), 27 deletions(-) diff --git a/pkgtool.pm b/pkgtool.pm index 89e8ca2..90843da 100644 --- a/pkgtool.pm +++ b/pkgtool.pm @@ -1,4 +1,4 @@ -package pkgtool; + package pkgtool; use strict; @@ -27,6 +27,7 @@ use Cwd; use Fcntl qw(:DEFAULT :mode);; use File::Spec; use Sys::Hostname; +use Digest::MD5; use IPC::Open3; use Win32; use Win32::File; @@ -3134,22 +3135,80 @@ sub check_if_driver_matches ($$) next unless defined $device; my $busname = $$device{Bus}; my $devname = $$device{Device}; -#print_log('global', DEBUG1, 'Checking device %s %s', $busname, $devname); + print_log('global', DEBUG4, 'Checking device %s %s', $busname, $devname); my $matches = 0; foreach my $filtrow (@$filter) { my $busfilter = $$filtrow{bus}; my $devfilter = $$filtrow{device}; next unless defined $busfilter && defined $devfilter; -#print_log('global', DEBUG1, ' against filter %s %s', $busfilter, $devfilter); + print_log('global', DEBUG4, ' against filter %s %s', $busfilter, $devfilter); next unless $busname =~ /$busfilter/ && $devname =~ /$devfilter/; -#print_log('global', DEBUG1, ' match found!'); + print_log('global', DEBUG4, ' match found!'); $matches = 1; last; } return 1 if $matches; } -#print_log('global', DEBUG1, 'No match found'); + print_log('global', DEBUG4, 'No match found'); + return 0; +} +sub get_file_checksum ($) +{ + my ($path) = @_; + + local *FILE; + my $ctx = Digest::MD5->new; + if (! open(FILE, '<', $path)) { + print_log('global', ERROR, 'Cannot open file %s: %s', $path, $!); + return undef; + } + if (! defined binmode(FILE)) { + print_log('global', ERROR, 'Cannot read file %s: %s', $path, $!); + close(FILE); + return undef; + } + $ctx->addfile(*FILE); + close(FILE); + return $ctx->hexdigest; +} + +sub compare_file_chksum ($$) +{ + my ($path, $chksum) = @_; + + my $infchksum = get_file_checksum($path); + if (! defined $infchksum) { + return 0; + } + return $infchksum eq $chksum; +} + +sub check_if_driver_present ($$$) +{ + my ($db, $drvdef, $infpath) = @_; + + my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size) = stat($infpath); + if (! defined $size) { + print_log('global', INFO, 'Cannot read .INF file size for %s: %s', $infpath, $!); + return 0; + } + my $infchksum = get_file_checksum($infpath); + if (! defined $infchksum) { + return 0; + } + my $infs = $$db{INFs}; + if (! defined $infs) { + print_log('global', INFO, 'Missing INF database'); + return 0; + } + foreach my $inf (values %$infs) { + next unless $$inf{Size} == $size; + if (compare_file_chksum($$inf{Path}, $infchksum)) { + print_log('global', INFO, 'Found driver %s installed as %s', $infpath, $$inf{Path}); + return 1; + } + } return 0; } @@ -3192,34 +3251,40 @@ sub handle_driver ($$$$$$) print_log('global', DEBUG2, 'Checking if driver %s is needed', $drvinstname); my $needed = check_if_driver_matches($db, $drvdef); if (! $needed) { - print_log('global', INFO, 'Skipping driver %s because relevant device is not present', $drvinstname); + print_log('global', INFO, 'Skipping driver %s because no relevant device is present', $drvinstname); push @{$$counters{SkipList}}, $drvinstname; $$counters{SkipCount}++; next; } - # check if present - print_log('global', WARNING, 'Driver %s to install: not installed - %s', - $drvinstname, $update? 'installing '.$infpath : 'INSTALL'); - if ($update) { - my $rc = 1; - if (defined $certpath) { - $rc = install_cert($certpath); - } - if ($rc) { - $rc = install_pnp_driver($infpath); - } - if (! $rc) { - push @{$$counters{FailList}}, $drvinstname; - $$counters{FailCount}++; - } - else { - push @{$$counters{InstalledList}}, $drvinstname; - $$counters{InstalledCount}++; - } + my $present = check_if_driver_present($db, $drvdef, $infpath); + if ($present) { + print_log('global', WARNING, 'Driver %s already installed%s', + $drvinstname, $update ? ' - nothing to do' : ''); } else { - push @{$$counters{ToInstallList}}, $drvinstname; - $$counters{ToInstallCount}++; + print_log('global', WARNING, 'Driver %s to install: not installed - %s', + $drvinstname, $update? 'installing '.$infpath : 'INSTALL'); + if ($update) { + my $rc = 1; + if (defined $certpath) { + $rc = install_cert($certpath); + } + if ($rc) { + $rc = install_pnp_driver($infpath); + } + if (! $rc) { + push @{$$counters{FailList}}, $drvinstname; + $$counters{FailCount}++; + } + else { + push @{$$counters{InstalledList}}, $drvinstname; + $$counters{InstalledCount}++; + } + } + else { + push @{$$counters{ToInstallList}}, $drvinstname; + $$counters{ToInstallCount}++; + } } } return 1;