diff options
author | Jacob Pipkin <d4wnr4z0r@yahoo.com> | 2012-05-08 00:44:49 -0500 |
---|---|---|
committer | Jacob Pipkin <d4wnr4z0r@yahoo.com> | 2012-05-08 00:44:49 -0500 |
commit | b7afd023a8e5ff86f751196984ba87dcb9d451cd (patch) | |
tree | 0e6add668d896be591972c4e7fb2a02b31488770 /SBO-Lib/lib | |
download | sbotools2-b7afd023a8e5ff86f751196984ba87dcb9d451cd.tar.xz |
initial repo add
Diffstat (limited to 'SBO-Lib/lib')
-rw-r--r-- | SBO-Lib/lib/SBO/.Lib.pm.swp | bin | 0 -> 32768 bytes | |||
-rw-r--r-- | SBO-Lib/lib/SBO/Lib.pm | 580 |
2 files changed, 580 insertions, 0 deletions
diff --git a/SBO-Lib/lib/SBO/.Lib.pm.swp b/SBO-Lib/lib/SBO/.Lib.pm.swp Binary files differnew file mode 100644 index 0000000..88b9abf --- /dev/null +++ b/SBO-Lib/lib/SBO/.Lib.pm.swp diff --git a/SBO-Lib/lib/SBO/Lib.pm b/SBO-Lib/lib/SBO/Lib.pm new file mode 100644 index 0000000..458df14 --- /dev/null +++ b/SBO-Lib/lib/SBO/Lib.pm @@ -0,0 +1,580 @@ +#!/usr/bin/env perl +# +# sbolib.sh +# shared functions for the sbo_ scripts. +# +# author: Jacob Pipkin <j@dawnrazor.net> +# date: Setting Orange, the 37th day of Discord in the YOLD 3178 +# license: WTFPL <http://sam.zoy.org/wtfpl/COPYING> + +package SBO::Lib 0.1; +my $version = "0.1"; + +require Exporter; + +@ISA = qw(Exporter); +@EXPORT = qw( + script_error + show_version + get_slack_version + check_slackbuilds_txt + fetch_tree + update_tree + get_installed_sbos + get_available_updates + check_sbo_name_validity + do_slack_build + make_clean + make_distclean + do_upgradepkg + get_sbo_location +); + +use warnings FATAL => 'all'; +use strict; +use File::Basename; +use English '-no_match_vars'; +use Tie::File; +use IO::File; +use Sort::Versions; +use Digest::MD5; +use File::Copy; +use File::Path qw(make_path remove_tree); +use Fcntl; + +$UID == 0 or print "This script requires root privileges.\n" and exit(1); + +our $conf_dir = '/etc/sbotools'; +our $conf_file = "$conf_dir/sbotools.conf"; +my @valid_conf_keys = ( + 'NOCLEAN', + 'DISTCLEAN', +# "JOBS", + 'PKG_DIR', + 'SBO_HOME' +); + +our %config; +if (-f $conf_file) { + open my $reader, '<', $conf_file; + my $text = do {local $/; <$reader>}; + %config = $text =~ /^(\w+)=(.*)$/mg; + close($reader); +} +for my $key (keys %config) { + unless ($key ~~ @valid_conf_keys) { + undef $config{$key}; + } +} +for (@valid_conf_keys) { + unless ($_ eq 'SBO_HOME') { + $config{$_} = "FALSE" unless exists $config{$_}; + } else { + $config{$_} = '/usr/sbo' unless exists $config{$_}; + } +} + + +my $distfiles = "$config{SBO_HOME}/distfiles"; +my $slackbuilds_txt = "$config{SBO_HOME}/SLACKBUILDS.TXT"; + +my $name_regex = '\ASLACKBUILD\s+NAME:\s+'; + +# this should be done a bit differently. +# +sub script_error { + unless (exists $_[0]) { + print "A fatal script error has occured. Exiting.\n"; + } else { + print "A fatal script error has occured:\n"; + print "$_[0]\n"; + print "Exiting.\n"; + } + exit(1); +} + +sub show_version { + print "sbotools version $version\n"; + print "licensed under the WTFPL\n"; + print "<http://sam.zoy.org/wtfpl/COPYING>\n"; +} + +sub get_slack_version { + if (-f '/etc/slackware-version') { + open my $slackver, '<', '/etc/slackware-version'; + chomp(my $line = <$slackver>); + close($slackver); + my $slk_version = split_line($line,' ',1); + $slk_version = '13.37' if $slk_version eq '13.37.0'; + return $slk_version; + } +} + +sub check_slackbuilds_txt { + if (-f $slackbuilds_txt) { + return 1; + } else { + print "I am unable to find SLACKBUILDS.TXT.\n"; + print "Perhaps you need to \"sbosnap fetch\"?\n"; + exit(1); + } +} + +sub rsync_sbo_tree { + my $slk_version = get_slack_version(); + my $cmd = 'rsync'; + my @arg = ('-a','--exclude=*.tar.gz','--exclude=*.tar.gz.asc'); + push(@arg,"rsync://slackbuilds.org/slackbuilds/$slk_version/*"); + push(@arg,$config{SBO_HOME}); + system($cmd,@arg); + print "Finished.\n"; + return 1; +} + +sub check_home { + my $sbo_home = $config{SBO_HOME}; + if (-d $sbo_home) { + opendir(my $home_handle,$sbo_home); + while (readdir $home_handle) { + next if /^\.[\.]{0,1}$/; + print "$sbo_home exists and is not empty. Exiting.\n"; + exit(1); + } + } else { + make_path($sbo_home) or print "Unable to create $sbo_home. Exiting.\n" + and exit(1); + } +} + +sub fetch_tree { + check_home(); + print "Pulling SlackBuilds tree...\n"; + rsync_sbo_tree(); +} + +sub update_tree { + check_slackbuilds_txt(); + print "Updating SlackBuilds tree...\n"; + rsync_sbo_tree(); +} + +sub get_installed_sbos { + my @installed; + opendir my $diread, '/var/log/packages'; + while (my $ls = readdir $diread) { + next if $ls =~ /\A\./; + if (index($ls,"SBo") != -1) { + my @split = split(/-/,reverse($ls),4); + my %hash; + $hash{name} = reverse($split[3]); + $hash{version} = reverse($split[2]); + push(@installed,\%hash); + } + } + return @installed; +} + +sub clean_line { + script_error('clean line requires an argument') + unless exists $_[0]; + chomp(my $line = shift); + $line =~ s/[\s"\\]//g; + return $line; +} + +#sub get_available_updates { +# check_slackbuilds_txt(); +# my @updates; +# my @pkg_list = get_installed_sbos(); +# my $sb_txt = IO::File->new($slackbuilds_txt,"r"); +# FIRST: for my $c (keys @pkg_list) { +# my $name = $pkg_list[$c]{name}; +# my $version = $pkg_list[$c]{version}; +# my $regex = qr/$name_regex\Q$name\E\n\z/; +# my $found = "FALSE"; +# SECOND: while (my $line = <$sb_txt>) { +# if ($line =~ $regex) { +# $found = "TRUE"; +# next SECOND; +# } +# if ($found eq "TRUE") { +# if ($line =~ /VERSION/) { +# $found = "FALSE"; +# my @split = split(' ',$line); +# my $sbo_version = clean_line($split[2]); +# if (versioncmp($sbo_version,$version) == 1) { +# my %hash = ( +# name => $name, +# installed => $version, +# update => $sbo_version, +# ); +# push(@updates,\%hash); +# } +# $sb_txt->seek(0,0); +# next FIRST; +# } +# } +# } +# } +# $sb_txt->close; +# return @updates; +#} + +# much nicer version above does not work with perl 5.12, at last on Slackware +# 13.37 - the regex within the SECOND loop (while inside for) will never ever +# match, or at least I couldn't find a way to make it do so. switch which is +# inside which, and it works, so we use this method for now. +# +# iterate over all the lines! +# +sub get_available_updates { + check_slackbuilds_txt(); + my (@updates,$index); + my @pkg_list = get_installed_sbos(); + open my $sb_txt, '<', $slackbuilds_txt; + my $found = 'FALSE'; + FIRST: while (my $line = <$sb_txt>) { + if ($found eq 'TRUE') { + if ($line =~ /VERSION/) { + $found = 'FALSE'; + my $sbo_version = split_line($line,' ',2); + if (versioncmp($sbo_version,$pkg_list[$index]{version}) == 1) { + my %hash = ( + name => $pkg_list[$index]{name}, + installed => $pkg_list[$index]{version}, + update => $sbo_version, + ); + push(@updates,\%hash); + } + } + } else { + SECOND: for my $c (keys @pkg_list) { + my $regex = qr/$name_regex\Q$pkg_list[$c]{name}\E\n\z/; + if ($line =~ $regex) { + $found = 'TRUE'; + $index = $c; + last SECOND; + } + } + } + } + close $sb_txt; + return @updates; +} + +sub check_sbo_name_validity { + script_error('check_sbo_name_validity requires an argument') + unless exists $_[0]; + my $sbo = shift; + check_slackbuilds_txt(); + my $valid = 'FALSE'; + my $regex = qr/$name_regex\Q$sbo\E\n\z/; + open my $sb_txt, '<', $slackbuilds_txt; + FIRST: while (my $line = <$sb_txt>) { + if ($line =~ $regex) { + $valid = 'TRUE'; + last FIRST; + } + } + close($sb_txt); + unless ($valid eq 'TRUE') { + print "$sbo does not exist in the SlackBuilds tree. Exiting.\n"; + exit(1); + } + return 1; +} + +sub get_sbo_location { + script_error('get_sbo_location requires an argument.Exiting.') + unless exists $_[0]; + my $sbo = shift; + check_slackbuilds_txt(); + my $found = 'FALSE'; + my $location; + my $regex = qr/$name_regex\Q$sbo\E\n\z/; + open my $sb_txt, '<', $slackbuilds_txt; + FIRST: while (my $line = <$sb_txt>) { + if ($line =~ $regex) { + $found = 'TRUE'; + next FIRST; + } + if ($found eq 'TRUE') { + if ($line =~ /LOCATION/) { + my $loc_line = split_line($line,' ',2); + $loc_line =~ s#^\./##; + $location = "$config{SBO_HOME}/$loc_line"; + last FIRST; + } + } + } + close($sb_txt); + return $location; +} + +sub split_line { + script_error('split_line requires three arguments') unless exists $_[2]; + my ($line,$pattern,$index) = @_; + if ($pattern eq ' ') { + my @split = split("$pattern",$line); + } else { + my @split = split(/$pattern/,$line); + } + return clean_line($split[$index]); +} + +sub split_equal_one { + script_error("split_equal_one requires an argument") unless exists $_[0]; + return split_line($_[0],'=',1); +} + +sub check_multilib { + return 1 if -f '/etc/profile.d/32dev.sh'; + return; +} + +sub find_download_info { + script_error('find_download_info requires four arguments.') + unless exists $_[3]; + my ($sbo,$location,$type,$x64) = @_; + my @return; + my $regex; + if ($type eq 'download') { + $regex = qr/^DOWNLOAD/; + } elsif ($type eq 'md5sum') { + $regex = qr/^MD5SUM/; + } + if ($x64) { + $regex = qr/${regex}_x86_64=/; + } else { + $regex = qr/$regex=/; + } + my $empty_regex = qr/=""$/; + my $back_regex = qr/\\$/; + my $more = 'FALSE'; + open my $info,'<',"$location/$sbo.info"; + FIRST: while (my $line = <$info>) { + unless ($more eq 'TRUE') { + if ($line =~ $regex) { + last FIRST if $line =~ $empty_regex; + unless ($link eq 'UNSUPPORTED') { + push(@return,split_equal_one($line)); + $more = 'TRUE' if $line =~ $back_regex; + } else { + last FIRST; + } + } + } else { + unless ($line =~ $back_regex) { + $more = 'FALSE'; + last FIRST; + } + $line = clean_line($line); + push(@return,$line); + } + } + close($return); + return @return if exists $return[0]; + return; +} + +# this is a bit wonky - if running a 64-bit system, we have to first see if +# DOWNLOAD_x86_64 is defined, and make sure it's not set to "UNSUPPORTED"; +# then if that doesn't yield anything, go through again pulling the DOWNLOAD +# contents. +# +# would like to think of a better way to handle this. +# +sub get_sbo_downloads { + script_error('get_sbo_downloads requires two arguments.') + unless exists $_[1]; + script_error('get_sbo_downloads given a non-directory.') unless -d $_[1]; + my ($sbo,$location) = @_; + chomp(my $arch = `uname -m`); + my (@links,@md5s); + if ($arch eq 'x86_64') { + my @links = find_download_info($sbo,$location,'download',1); + my @md5s = find_download_info($sbo,$location,'md5sum',1); + } + unless (exists $links[0]) { + my @links = find_download_info($sbo,$location,'download',0); + my @md5s = find_download_info($sbo,$location,'md5sum',0); + } + my @downloads; + for my $c (keys @links) { + my %hash = (link => $links[$c],md5sum => $md5s[$c]); + push (@downloads,\%hash); + } + return @downloads; +} + +sub compute_md5sum { + script_error('compute_md5sum requires an argument.') unless exists $_[0]; + script_error('compute_md5sum argument is not a file.') unless -f $_[0]; + my $filename = shift; + open my $reader, '<', $filename; + my $md5 = Digest::MD5->new; + $md5->addfile($reader); + my $md5sum = $md5->hexdigest; + close($reader); + return $md5sum; +} + +sub get_filename_from_link { + script_error('get_filename_from_link requires an argument') + unless exists $_[0]; + my @split = split('/',reverse($_[0]),2); + chomp(my $filename = $distfiles .'/'. reverse($split[0])); + return $filename; +} + +sub check_distfile { + script_error('check_distfile requires an argument.') unless exists $_[0]; + my $filename = get_filename_from_link($_[0]); + return unless -d $distfiles; + return unless -f $filename; + my $md5sum = compute_md5sum($filename); + return unless $_[1] eq $md5sum; + return 1; +} + +sub get_distfile { + script_error('get_distfile requires an argument') unless exists $_[1]; + my ($link,$expected_md5sum) = @_; + my $filename = get_filename_from_link($link); + mkdir($distfiles) unless -d $distfiles; + chdir($distfiles); + my $out = system("wget $link"); + return unless $out == 0; + my $md5sum = compute_md5sum($filename); + if ($md5sum ne $expected_md5sum) { + print "md5sum failure for $filename.\n"; + exit(1); + } + return 1; +} + +sub get_sbo_version { + script_error('get_sbo_version requires two arguments.') + unless exists $_[1]; + my ($sbo,$location) = @_; + my $version; + open my $info, '<', "$location/$sbo.info"; + my $version_regex = qr/\AVERSION=/; + FIRST: while (my $line = <$info>) { + if ($line =~ $version_regex) { + $version = split_equal_one($line); + last FIRST; + } + } + close($info); + return $version; +} + +sub get_symlink_from_filename { + script_error('get_symlink_from_filename requires two arguments') + unless exists $_[1]; + script_error('get_symlink_from_filename first argument is not a file') + unless -f $_[0]; + my @split = split('/',reverse($_[0]),2); + my $fn = reverse($split[0]); + return "$_[1]/$fn"; +} + +sub check_x32 { + script_error('check_x32 requires two arguments.') unless exists $_[1]; + my ($sbo,$location) = @_; + open my $info,'<',"$location/$sbo.info"; + my $regex = qr/^DOWNLOAD_x86_64/; + FIRST: while (my $line = <$info>) { + if ($line =~ $regex) { + return 1 if index($line,'UNSUPPORTED') != -1; + } + } + return; +} + +sub check_multilib { + return 1 if -f '/etc/profile.d/32dev.sh'; + return; +} + +sub do_slack_build { + script_error('do_slack_build requires two arguments.') unless exists $_[1]; + my ($jobs,$sbo) = @_; + my $sbo_home = $config{SBO_HOME}; + my $location = get_sbo_location($sbo); + my $x32 = check_x32($sbo,$location); + if ($x32) { + if (! check_multilib()) { + print "$sbo is 32-bit only, however, this system does not appear +to be multilib ready\n"; + exit 1 + } + } + my $version = get_sbo_version($sbo,$location); + my @downloads = get_sbo_downloads($sbo,$location); + my @symlinks; + for my $c (keys @downloads) { + my $link = $downloads[$c]{link}; + my $md5sum = $downloads[$c]{md5sum}; + my $filename = get_filename_from_link($link); + unless (check_distfile($link,$md5sum)) { + die unless get_distfile($link,$md5sum); + } + my $symlink = get_symlink_from_filename($filename,$location); + push(@symlinks,$symlink); + symlink($filename,$symlink); + } + chdir($location); + chmod(0755,"$location/$sbo.SlackBuild"); + my $cmd; + if ($x32) { + $cmd = ". /etc/profile.d/32dev.sh && $location/$sbo.SlackBuild"; + } else { + $cmd = "$location/$sbo.SlackBuild"; + } + my $out = system($cmd); + die unless $out == 0; + unlink($_) for (@symlinks); + return $version; +} + +sub make_clean { + script_error('make_clean requires two arguments.') unless exists $_[1]; + my ($sbo,$version) = @_; + print "Cleaning for $sbo-$version...\n"; + remove_tree("/tmp/SBo/$sbo-$version") if -d "/tmp/SBo/$sbo-$version"; + remove_tree("/tmp/SBo/package-$sbo") if -d "/tmp/SBo/package-$sbo"; + return 1; +} + +sub make_distclean { + script_error('make_distclean requires two arguments.') unless exists $_[1]; + my ($sbo,$version) = @_; + make_clean($sbo,$version); + print "Distcleaning for $sbo-$version...\n"; + my $location = get_sbo_location($sbo); + my @downloads = get_sbo_downloads($sbo,$location); + for my $dl (@downloads) { + my $filename = get_filename_from_link($dl); + unlink($filename) if -f $filename; + } + return 1; +} + +sub do_upgradepkg { + script_error('do_upgradepkg requires two arguments.') unless exists $_[1]; + my ($sbo,$version) = @_; + my $pkg; + my $pkg_regex = qr/^(\Q$sbo\E-\Q$version\E-[^-]+-.*_SBo.t[xblg]z)$/; + opendir my $diread, '/tmp/'; + FIRST: while (my $ls = readdir $diread) { + if ($ls =~ $pkg_regex) { + chomp($pkg = "/tmp/$1"); + last FIRST; + } + } + system("/sbin/upgradepkg --reinstall --install-new $pkg"); + return $pkg; +} + |