Igor Sarkisov | 980c012 | 2020-10-06 12:16:43 -0700 | [diff] [blame^] | 1 | #!/usr/bin/perl |
| 2 | # -*-perl-*- |
| 3 | # |
| 4 | # Copyright © 1996 Andy Guy <awpguy@acs.ucalgary.ca> |
| 5 | # Copyright © 1998 Martin Schulze <joey@infodrom.north.de> |
| 6 | # Copyright © 1999, 2009 Raphaël Hertzog <hertzog@debian.org> |
| 7 | # |
| 8 | # This program has been distributed under the terms of the GNU GPL. |
| 9 | |
| 10 | use strict; |
| 11 | use warnings; |
| 12 | |
| 13 | use vars qw(%config $ftp); |
| 14 | #use diagnostics; |
| 15 | |
| 16 | use lib '/usr/lib/perl5/Debian'; |
| 17 | use lib '/usr/share/perl5/Debian'; |
| 18 | |
| 19 | eval q{ |
| 20 | use Net::FTP; |
| 21 | use File::Path; |
| 22 | use File::Basename; |
| 23 | use File::Find; |
| 24 | use Data::Dumper; |
| 25 | }; |
| 26 | if ($@) { |
| 27 | print STDERR "Please install the 'perl' package if you want to use the\n" . |
| 28 | "FTP access method of dselect.\n\n"; |
| 29 | exit 1; |
| 30 | } |
| 31 | |
| 32 | use Dselect::Ftp; |
| 33 | |
| 34 | # exit value |
| 35 | my $exit = 0; |
| 36 | |
| 37 | # deal with arguments |
| 38 | my $vardir = $ARGV[0]; |
| 39 | my $method = $ARGV[1]; |
| 40 | my $option = $ARGV[2]; |
| 41 | |
| 42 | if ($option eq "manual" ) { |
| 43 | print "manual mode not supported yet\n"; |
| 44 | exit 1; |
| 45 | } |
| 46 | #print "vardir: $vardir, method: $method, option: $option\n"; |
| 47 | |
| 48 | my $methdir = "$vardir/methods/ftp"; |
| 49 | |
| 50 | # get info from control file |
| 51 | read_config("$methdir/vars"); |
| 52 | |
| 53 | chdir "$methdir"; |
| 54 | mkpath(["$methdir/$config{'dldir'}"], 0, 0755); |
| 55 | |
| 56 | |
| 57 | #Read md5sums already calculated |
| 58 | my %md5sums; |
| 59 | if (-f "$methdir/md5sums") { |
| 60 | local $/; |
| 61 | open(MD5SUMS, "$methdir/md5sums") || |
| 62 | die "Couldn't read file $methdir/md5sums"; |
| 63 | my $code = <MD5SUMS>; |
| 64 | close MD5SUMS; |
| 65 | use vars qw($VAL1); |
| 66 | my $res = eval $code; |
| 67 | if ($@) { |
| 68 | die "Couldn't eval $methdir/md5sums content: $@\n"; |
| 69 | } |
| 70 | if (ref($res)) { %md5sums = %{$res} } |
| 71 | } |
| 72 | |
| 73 | # get a block |
| 74 | # returns a ref to a hash containing flds->fld contents |
| 75 | # white space from the ends of lines is removed and newlines added |
| 76 | # (no trailing newline). |
| 77 | # die's if something unexpected happens |
| 78 | sub getblk { |
| 79 | my $fh = shift; |
| 80 | my %flds; |
| 81 | my $fld; |
| 82 | while (<$fh>) { |
| 83 | if ( ! /^$/ ) { |
| 84 | FLDLOOP: while (1) { |
| 85 | if ( /^(\S+):\s*(.*)\s*$/ ) { |
| 86 | $fld = lc($1); |
| 87 | $flds{$fld} = $2; |
| 88 | while (<$fh>) { |
| 89 | if ( /^$/ ) { |
| 90 | return %flds; |
| 91 | } elsif ( /^(\s.*)$/ ) { |
| 92 | $flds{$fld} = $flds{$fld} . "\n" . $1; |
| 93 | } else { |
| 94 | next FLDLOOP; |
| 95 | } |
| 96 | } |
| 97 | return %flds; |
| 98 | } else { |
| 99 | die "Expected a start of field line, but got:\n$_"; |
| 100 | } |
| 101 | } |
| 102 | } |
| 103 | } |
| 104 | return %flds; |
| 105 | } |
| 106 | |
| 107 | # process status file |
| 108 | # create curpkgs hash with version (no version implies not currently installed) |
| 109 | # of packages we want |
| 110 | print "Processing status file...\n"; |
| 111 | my %curpkgs; |
| 112 | sub procstatus { |
| 113 | my (%flds, $fld); |
| 114 | open (STATUS, "$vardir/status") or die "Could not open status file"; |
| 115 | while (%flds = getblk(\*STATUS), %flds) { |
| 116 | if($flds{'status'} =~ /^install ok/) { |
| 117 | my $cs = (split(/ /, $flds{'status'}))[2]; |
| 118 | if(($cs eq "not-installed") || |
| 119 | ($cs eq "half-installed") || |
| 120 | ($cs eq "config-files")) { |
| 121 | $curpkgs{$flds{'package'}} = ""; |
| 122 | } else { |
| 123 | $curpkgs{$flds{'package'}} = $flds{'version'}; |
| 124 | } |
| 125 | } |
| 126 | } |
| 127 | close(STATUS); |
| 128 | } |
| 129 | procstatus(); |
| 130 | |
| 131 | sub dcmpvers { |
| 132 | my($a, $p, $b) = @_; |
| 133 | my ($r); |
| 134 | $r = system("/usr/bin/dpkg", "--compare-versions", "$a", "$p", "$b"); |
| 135 | $r = $r/256; |
| 136 | if ($r == 0) { |
| 137 | return 1; |
| 138 | } elsif ($r == 1) { |
| 139 | return 0; |
| 140 | } |
| 141 | die "dpkg --compare-versions $a $p $b - failed with $r"; |
| 142 | } |
| 143 | |
| 144 | # process package files, looking for packages to install |
| 145 | # create a hash of these packages pkgname => version, filenames... |
| 146 | # filename => md5sum, size |
| 147 | # for all packages |
| 148 | my %pkgs; |
| 149 | my %pkgfiles; |
| 150 | sub procpkgfile { |
| 151 | my $fn = shift; |
| 152 | my $site = shift; |
| 153 | my $dist = shift; |
| 154 | my(@files,@sizes,@md5sums,$pkg,$ver,$fl,$nfs,$fld); |
| 155 | my(%flds); |
| 156 | open(PKGFILE, "$fn") or die "Could not open package file $fn"; |
| 157 | while(%flds = getblk(\*PKGFILE), %flds) { |
| 158 | $pkg = $flds{'package'}; |
| 159 | $ver = $curpkgs{$pkg}; |
| 160 | @files = split(/[\s\n]+/, $flds{'filename'}); |
| 161 | @sizes = split(/[\s\n]+/, $flds{'size'}); |
| 162 | @md5sums = split(/[\s\n]+/, $flds{'md5sum'}); |
| 163 | if ( defined($ver) && ( ($ver eq "") || dcmpvers( $ver, "lt", $flds{'version'} ) )) { |
| 164 | $pkgs{$pkg} = [ $flds{'version'}, [ @files ], $site ]; |
| 165 | $curpkgs{$pkg} = $flds{'version'}; |
| 166 | } |
| 167 | $nfs = scalar(@files); |
| 168 | if(($nfs != scalar(@sizes)) || ($nfs != scalar(@md5sums)) ) { |
| 169 | print "Different number of filenames, sizes and md5sums for $flds{'package'}\n"; |
| 170 | } else { |
| 171 | my $i = 0; |
| 172 | foreach $fl (@files) { |
| 173 | $pkgfiles{$fl} = [ $md5sums[$i], $sizes[$i], $site, $dist ]; |
| 174 | $i++; |
| 175 | } |
| 176 | } |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | print "\nProcessing Package files...\n"; |
| 181 | my ($dist,$site,$fn,$i,$j); |
| 182 | $i = 0; |
| 183 | foreach $site (@{$config{'site'}}) { |
| 184 | $j = 0; |
| 185 | foreach $dist (@{$site->[2]}) { |
| 186 | $fn = $dist; |
| 187 | $fn =~ tr#/#_#; |
| 188 | $fn = "Packages.$site->[0].$fn"; |
| 189 | if (-f $fn) { |
| 190 | print " $site->[0] $dist...\n"; |
| 191 | procpkgfile($fn,$i,$j); |
| 192 | } else { |
| 193 | print "Could not find packages file for $site->[0] $dist distribution (re-run Update)\n" |
| 194 | } |
| 195 | $j++; |
| 196 | } |
| 197 | $i++; |
| 198 | } |
| 199 | |
| 200 | my $dldir = $config{'dldir'}; |
| 201 | # md5sum |
| 202 | sub md5sum($) { |
| 203 | my $fn = shift; |
| 204 | my $m = `md5sum $fn`; |
| 205 | $m = (split(" ", $m))[0]; |
| 206 | $md5sums{"$dldir/$fn"} = $m; |
| 207 | return $m; |
| 208 | } |
| 209 | |
| 210 | # construct list of files to get |
| 211 | # hash of filenames => size of downloaded part |
| 212 | # query user for each paritial file |
| 213 | print "\nConstructing list of files to get...\n"; |
| 214 | my %downloads; |
| 215 | my ($pkg, $dir, @info, @files, $csize, $size); |
| 216 | my $totsize = 0; |
| 217 | foreach $pkg (keys(%pkgs)) { |
| 218 | @files = @{$pkgs{$pkg}[1]}; |
| 219 | foreach $fn (@files) { |
| 220 | #Look for a partial file |
| 221 | if (-f "$dldir/$fn.partial") { |
| 222 | rename "$dldir/$fn.partial", "$dldir/$fn"; |
| 223 | } |
| 224 | $dir = dirname($fn); |
| 225 | if(! -d "$dldir/$dir") { |
| 226 | mkpath(["$dldir/$dir"], 0, 0755); |
| 227 | } |
| 228 | @info = @{$pkgfiles{$fn}}; |
| 229 | $csize = int($info[1]/1024)+1; |
| 230 | if(-f "$dldir/$fn") { |
| 231 | $size = -s "$dldir/$fn"; |
| 232 | if($info[1] > $size) { |
| 233 | # partial download |
| 234 | if(yesno("y", "continue file: $fn (" . nb($size) ."/" . |
| 235 | nb($info[1]). ")")) { |
| 236 | $downloads{$fn} = $size; |
| 237 | $totsize += $csize - int($size/1024); |
| 238 | } else { |
| 239 | $downloads{$fn} = 0; |
| 240 | $totsize += $csize; |
| 241 | } |
| 242 | } else { |
| 243 | # check md5sum |
| 244 | if (! exists $md5sums{"$dldir/$fn"}) { |
| 245 | $md5sums{"$dldir/$fn"} = md5sum("$dldir/$fn"); |
| 246 | } |
| 247 | if ($md5sums{"$dldir/$fn"} eq $info[0]) { |
| 248 | print "already got: $fn\n"; |
| 249 | } else { |
| 250 | print "corrupted: $fn\n"; |
| 251 | $downloads{$fn} = 0; |
| 252 | } |
| 253 | } |
| 254 | } else { |
| 255 | my $ffn = $fn; |
| 256 | $ffn =~ s/binary-[^\/]+/.../; |
| 257 | print "want: " . |
| 258 | $config{'site'}[$pkgfiles{$fn}[2]][0] . " $ffn (${csize}k)\n"; |
| 259 | $downloads{$fn} = 0; |
| 260 | $totsize += $csize; |
| 261 | } |
| 262 | } |
| 263 | } |
| 264 | |
| 265 | my $avsp = `df -Pk $dldir| awk '{ print \$4}' | tail -n 1`; |
| 266 | chomp $avsp; |
| 267 | |
| 268 | print "\nApproximate total space required: ${totsize}k\n"; |
| 269 | print "Available space in $dldir: ${avsp}k\n"; |
| 270 | |
| 271 | #$avsp = `df -k $::dldir| paste -s | awk '{ print \$11}'`; |
| 272 | #chomp $avsp; |
| 273 | |
| 274 | if($totsize == 0) { |
| 275 | print "Nothing to get."; |
| 276 | } else { |
| 277 | if($totsize > $avsp) { |
| 278 | print "Space required is greater than available space,\n"; |
| 279 | print "you will need to select which items to get.\n"; |
| 280 | } |
| 281 | # ask user which files to get |
| 282 | if(($totsize > $avsp) || yesno("n", "Do you want to select the files to get")) { |
| 283 | $totsize = 0; |
| 284 | my @files = sort(keys(%downloads)); |
| 285 | my $fn; |
| 286 | my $def = "y"; |
| 287 | foreach $fn (@files) { |
| 288 | my @info = @{$pkgfiles{$fn}}; |
| 289 | my $csize = int($info[1] / 1024) + 1; |
| 290 | my $rsize = int(($info[1] - $downloads{$fn}) / 1024) + 1; |
| 291 | if ($rsize + $totsize > $avsp) { |
| 292 | print "no room for: $fn\n"; |
| 293 | delete $downloads{$fn}; |
| 294 | } else { |
| 295 | if(yesno($def, $downloads{$fn} |
| 296 | ? "download: $fn ${rsize}k/${csize}k (total = ${totsize}k)" |
| 297 | : "download: $fn ${rsize}k (total = ${totsize}k)")) { |
| 298 | $def = "y"; |
| 299 | $totsize += $rsize; |
| 300 | } else { |
| 301 | $def = "n"; |
| 302 | delete $downloads{$fn}; |
| 303 | } |
| 304 | } |
| 305 | } |
| 306 | } |
| 307 | } |
| 308 | |
| 309 | sub download() { |
| 310 | |
| 311 | my $i = 0; |
| 312 | my ($site, $ftp); |
| 313 | |
| 314 | foreach $site (@{$config{'site'}}) { |
| 315 | |
| 316 | my @getfiles = grep { $pkgfiles{$_}[2] == $i } keys %downloads; |
| 317 | my @pre_dist = (); # Directory to add before $fn |
| 318 | |
| 319 | #Scan distributions for looking at "(../)+/dir/dir" |
| 320 | my ($n,$cp); |
| 321 | $cp = -1; |
| 322 | foreach (@{$site->[2]}) { |
| 323 | $cp++; |
| 324 | $pre_dist[$cp] = ""; |
| 325 | $n = (s#\.\./#../#g); |
| 326 | next if (! $n); |
| 327 | if (m#^((?:\.\./){$n}(?:[^/]+/){$n})#) { |
| 328 | $pre_dist[$cp] = $1; |
| 329 | } |
| 330 | } |
| 331 | |
| 332 | if (! @getfiles) { $i++; next; } |
| 333 | |
| 334 | $ftp = do_connect ($site->[0], #$::ftpsite, |
| 335 | $site->[4], #$::username, |
| 336 | $site->[5], #$::password, |
| 337 | $site->[1], #$::ftpdir, |
| 338 | $site->[3], #$::passive, |
| 339 | $config{'use_auth_proxy'}, |
| 340 | $config{'proxyhost'}, |
| 341 | $config{'proxylogname'}, |
| 342 | $config{'proxypassword'}); |
| 343 | |
| 344 | $::ftp = $ftp; |
| 345 | local $SIG{'INT'} = sub { die "Interrupted !\n"; }; |
| 346 | |
| 347 | my ($fn,$rsize,$res,$pre); |
| 348 | foreach $fn (@getfiles) { |
| 349 | $pre = $pre_dist[$pkgfiles{$fn}[3]] || ""; |
| 350 | if ($downloads{$fn}) { |
| 351 | $rsize = ${pkgfiles{$fn}}[1] - $downloads{$fn}; |
| 352 | print "getting: $pre$fn (". nb($rsize) . "/" . |
| 353 | nb($pkgfiles{$fn}[1]) . ")\n"; |
| 354 | } else { |
| 355 | print "getting: $pre$fn (". nb($pkgfiles{$fn}[1]) . ")\n"; |
| 356 | } |
| 357 | $res = $ftp->get("$pre$fn", "$dldir/$fn", $downloads{$fn}); |
| 358 | if(! $res) { |
| 359 | my $r = $ftp->code(); |
| 360 | print $ftp->message() . "\n"; |
| 361 | if (!($r == 550 || $r == 450)) { |
| 362 | return 1; |
| 363 | } else { |
| 364 | #Try to find another file or this package |
| 365 | print "Looking for another version of the package...\n"; |
| 366 | my ($dir,$package) = ($fn =~ m#^(.*)/([^/]+)_[^/]+.deb$#); |
| 367 | my $protected = $package; |
| 368 | $protected =~ s/\+/\\\+/g; |
| 369 | my $list = $ftp->ls("$pre$dir"); |
| 370 | if ($ftp->ok() && ref($list)) { |
| 371 | foreach (@{$list}) { |
| 372 | if (m/($dir\/${protected}_[^\/]+.deb)/i) { |
| 373 | print "Package found : $_\n"; |
| 374 | print "getting: $_ (size not known)\n"; |
| 375 | $res = $ftp->get($_, "$dldir/$1"); |
| 376 | if (! $res) { |
| 377 | $r = $ftp->code(); |
| 378 | print $ftp->message() . "\n"; |
| 379 | return 1 if ($r != 550 and $r != 450); |
| 380 | } |
| 381 | } |
| 382 | } |
| 383 | } |
| 384 | } |
| 385 | } |
| 386 | # fully got, remove it from list in case we have to re-download |
| 387 | delete $downloads{$fn}; |
| 388 | } |
| 389 | $ftp->quit(); |
| 390 | $i++; |
| 391 | } |
| 392 | return 0; |
| 393 | } |
| 394 | |
| 395 | # download stuff (protect from ^C) |
| 396 | if($totsize != 0) { |
| 397 | if(yesno("y", "\nDo you want to download the required files")) { |
| 398 | DOWNLOAD_TRY: while (1) { |
| 399 | print "Downloading files... use ^C to stop\n"; |
| 400 | eval { |
| 401 | if ((download() == 1) && yesno("y", "\nDo you want to retry downloading at once")) { |
| 402 | next DOWNLOAD_TRY; |
| 403 | } |
| 404 | }; |
| 405 | if($@ =~ /Interrupted|Timeout/i ) { |
| 406 | # close the FTP connection if needed |
| 407 | if ((ref($::ftp) =~ /Net::FTP/) and ($@ =~ /Interrupted/i)) { |
| 408 | $::ftp->abort(); |
| 409 | $::ftp->quit(); |
| 410 | undef $::ftp; |
| 411 | } |
| 412 | print "FTP ERROR\n"; |
| 413 | if (yesno("y", "\nDo you want to retry downloading at once")) { |
| 414 | # get the first $fn that foreach would give: |
| 415 | # this is the one that got interrupted. |
| 416 | my $ffn; |
| 417 | MY_ITER: foreach $ffn (keys(%downloads)) { |
| 418 | $fn = $ffn; |
| 419 | last MY_ITER; |
| 420 | } |
| 421 | my $size = -s "$dldir/$fn"; |
| 422 | # partial download |
| 423 | if(yesno("y", "continue file: $fn (at $size)")) { |
| 424 | $downloads{$fn} = $size; |
| 425 | } else { |
| 426 | $downloads{$fn} = 0; |
| 427 | } |
| 428 | next DOWNLOAD_TRY; |
| 429 | } else { |
| 430 | $exit = 1; |
| 431 | last DOWNLOAD_TRY; |
| 432 | } |
| 433 | } elsif ($@) { |
| 434 | print "An error occurred ($@) : stopping download\n"; |
| 435 | } |
| 436 | last DOWNLOAD_TRY; |
| 437 | } |
| 438 | } |
| 439 | } |
| 440 | |
| 441 | # remove duplicate packages (keep latest versions) |
| 442 | # move half downloaded files out of the way |
| 443 | # delete corrupted files |
| 444 | print "\nProcessing downloaded files...(for corrupt/old/partial)\n"; |
| 445 | my %vers; # package => version |
| 446 | my %files; # package-version => files... |
| 447 | |
| 448 | # check a deb or split deb file |
| 449 | # return 1 if it a deb file, 2 if it is a split deb file |
| 450 | # else 0 |
| 451 | sub chkdeb($) { |
| 452 | my ($fn) = @_; |
| 453 | # check to see if it is a .deb file |
| 454 | if(!system("dpkg-deb --info $fn 2>&1 >/dev/null && dpkg-deb --contents $fn 2>&1 >/dev/null")) { |
| 455 | return 1; |
| 456 | } elsif(!system("dpkg-split --info $fn 2>&1 >/dev/null")) { |
| 457 | return 2; |
| 458 | } |
| 459 | return 0; |
| 460 | } |
| 461 | sub getdebinfo($) { |
| 462 | my ($fn) = @_; |
| 463 | my $type = chkdeb($fn); |
| 464 | my ($pkg, $ver); |
| 465 | if($type == 1) { |
| 466 | open(PKGFILE, "dpkg-deb --field $fn |"); |
| 467 | my %fields = getblk(\*PKGFILE); |
| 468 | close(PKGFILE); |
| 469 | $pkg = $fields{'package'}; |
| 470 | $ver = $fields{'version'}; |
| 471 | if($fields{'package_revision'}) { $ver .= '-' . $fields{'package_revision'}; } |
| 472 | return $pkg, $ver; |
| 473 | } elsif ( $type == 2) { |
| 474 | open(PKGFILE, "dpkg-split --info $fn|"); |
| 475 | while(<PKGFILE>) { |
| 476 | /Part of package:\s*(\S+)/ and $pkg = $+; |
| 477 | /\.\.\. version:\s*(\S+)/ and $ver = $+; |
| 478 | } |
| 479 | close(PKGFILE); |
| 480 | return $pkg, $ver; |
| 481 | } |
| 482 | print "could not figure out type of $fn\n"; |
| 483 | return $pkg, $ver; |
| 484 | } |
| 485 | |
| 486 | # process deb file to make sure we only keep latest versions |
| 487 | sub prcdeb($$) { |
| 488 | my ($dir, $fn) = @_; |
| 489 | my ($pkg, $ver) = getdebinfo($fn); |
| 490 | if(!defined($pkg) || !defined($ver)) { |
| 491 | print "could not get package info from file\n"; |
| 492 | return 0; |
| 493 | } |
| 494 | if($vers{$pkg}) { |
| 495 | if(dcmpvers($vers{$pkg}, "eq", $ver)) { |
| 496 | $files{$pkg . $ver} = [ $files{$pkg . $ver }, "$dir/$fn" ]; |
| 497 | } elsif (dcmpvers($vers{$pkg}, "gt", $ver)) { |
| 498 | print "old version\n"; |
| 499 | unlink $fn; |
| 500 | } else { # else $ver is gt current version |
| 501 | my ($c); |
| 502 | foreach $c (@{$files{$pkg . $vers{$pkg}}}) { |
| 503 | print "replaces: $c\n"; |
| 504 | unlink "$vardir/methods/ftp/$dldir/$c"; |
| 505 | } |
| 506 | $vers{$pkg} = $ver; |
| 507 | $files{$pkg . $ver} = [ "$dir/$fn" ]; |
| 508 | } |
| 509 | } else { |
| 510 | $vers{$pkg} = $ver; |
| 511 | $files{$pkg . $ver} = [ "$dir/$fn" ]; |
| 512 | } |
| 513 | } |
| 514 | |
| 515 | sub prcfile() { |
| 516 | my ($fn) = $_; |
| 517 | if (-f $fn and $fn ne '.') { |
| 518 | my $dir = "."; |
| 519 | if (length($File::Find::dir) > length($dldir)) { |
| 520 | $dir = substr($File::Find::dir, length($dldir)+1); |
| 521 | } |
| 522 | print "$dir/$fn\n"; |
| 523 | if(defined($pkgfiles{"$dir/$fn"})) { |
| 524 | my @info = @{$pkgfiles{"$dir/$fn"}}; |
| 525 | my $size = -s $fn; |
| 526 | if($size == 0) { |
| 527 | print "zero length file\n"; |
| 528 | unlink $fn; |
| 529 | } elsif($size < $info[1]) { |
| 530 | print "partial file\n"; |
| 531 | rename $fn, "$fn.partial"; |
| 532 | } elsif(( (exists $md5sums{"$dldir/$fn"}) |
| 533 | and ($md5sums{"$dldir/$fn"} ne $info[0]) ) |
| 534 | or |
| 535 | (md5sum($fn) ne $info[0])) { |
| 536 | print "corrupt file\n"; |
| 537 | unlink $fn; |
| 538 | } else { |
| 539 | prcdeb($dir, $fn); |
| 540 | } |
| 541 | } elsif($fn =~ /.deb$/) { |
| 542 | if(chkdeb($fn)) { |
| 543 | prcdeb($dir, $fn); |
| 544 | } else { |
| 545 | print "corrupt file\n"; |
| 546 | unlink $fn; |
| 547 | } |
| 548 | } else { |
| 549 | print "non-debian file\n"; |
| 550 | } |
| 551 | } |
| 552 | } |
| 553 | find(\&prcfile, "$dldir/"); |
| 554 | |
| 555 | # install .debs |
| 556 | if(yesno("y", "\nDo you want to install the files fetched")) { |
| 557 | print "Installing files...\n"; |
| 558 | #Installing pre-dependent package before ! |
| 559 | my (@flds, $package, @filename, $r); |
| 560 | while (@flds = `dpkg --predep-package`, $? == 0) { |
| 561 | foreach (@flds) { |
| 562 | s/\s*\n//; |
| 563 | $package= $_ if s/^Package: //i; |
| 564 | @filename= split(/ +/,$_) if s/^Filename: //i; |
| 565 | } |
| 566 | @filename = map { "$dldir/$_" } @filename; |
| 567 | next if (! @filename); |
| 568 | $r = system('dpkg', '-iB', '--', @filename); |
| 569 | if ($r) { print "DPKG ERROR\n"; $exit = 1; } |
| 570 | } |
| 571 | #Installing other packages after |
| 572 | $r = system("dpkg", "-iGREOB", $dldir); |
| 573 | if($r) { |
| 574 | print "DPKG ERROR\n"; |
| 575 | $exit = 1; |
| 576 | } |
| 577 | } |
| 578 | |
| 579 | sub removeinstalled { |
| 580 | my $fn = $_; |
| 581 | if (-f $fn and $fn ne '.') { |
| 582 | my $dir = "."; |
| 583 | if (length($File::Find::dir) > length($dldir)) { |
| 584 | $dir = substr($File::Find::dir, length($dldir)+1); |
| 585 | } |
| 586 | if($fn =~ /.deb$/) { |
| 587 | my($pkg, $ver) = getdebinfo($fn); |
| 588 | if(!defined($pkg) || !defined($ver)) { |
| 589 | print "Could not get info for: $dir/$fn\n"; |
| 590 | } else { |
| 591 | if($curpkgs{$pkg} and dcmpvers($ver, "le", $curpkgs{$pkg})) { |
| 592 | print "deleting: $dir/$fn\n"; |
| 593 | unlink $fn; |
| 594 | } else { |
| 595 | print "leaving: $dir/$fn\n"; |
| 596 | } |
| 597 | } |
| 598 | } else { |
| 599 | print "non-debian: $dir/$fn\n"; |
| 600 | } |
| 601 | } |
| 602 | } |
| 603 | |
| 604 | # remove .debs that have been installed (query user) |
| 605 | # first need to reprocess status file |
| 606 | if(yesno("y", "\nDo you wish to delete the installed package (.deb) files?")) { |
| 607 | print "Removing installed files...\n"; |
| 608 | %curpkgs = (); |
| 609 | procstatus(); |
| 610 | find(\&removeinstalled, "$dldir/"); |
| 611 | } |
| 612 | |
| 613 | # remove whole ./debian directory if user wants to |
| 614 | if(yesno("n", "\nDo you want to remove $dldir directory?")) { |
| 615 | rmtree("$dldir"); |
| 616 | } |
| 617 | |
| 618 | #Store useful md5sums |
| 619 | foreach (keys %md5sums) { |
| 620 | next if (-f $_); |
| 621 | delete $md5sums{$_}; |
| 622 | } |
| 623 | open(MD5SUMS, ">$methdir/md5sums") || |
| 624 | die "Can't open $methdir/md5sums in write mode : $!\n"; |
| 625 | print MD5SUMS Dumper(\%md5sums); |
| 626 | close MD5SUMS; |
| 627 | |
| 628 | exit $exit; |