diff --git a/Makefile b/Makefile index 5127db4..59955c7 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -DEPENDS = binutils,coreutils,gzip,perl=5.20.0,tar +DEPENDS = binutils,coreutils,gzip,perl>=5.20.0,tar ARCH = x86_64 URL = DESC = The Snaplinux package management system @@ -16,7 +16,7 @@ DESC = The Snaplinux package management system ARCHIVE := '' SRCDIR := $(PWD)/SRC/snap PATCHDIR := $(PWD)/SRC/patches -VERSION := 0.4-0 +VERSION := 0.5-0 MAKEINST = make install diff --git a/SNAP/usher b/SNAP/usher deleted file mode 100755 index b402e27..0000000 --- a/SNAP/usher +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -set -e - -case $1 in - preinst) - exit 0 - ;; - postinst) - setpass=`cat ${TARGET}/etc/shadow|grep ^root|awk -F':' '{print $2}'` - - if [ "$setpass" == 'SETPASS' ]; then - echo "Setting root password" - - if [[ ${TARGET} ]]; then - if ! mountpoint ${TARGET}/dev; then - mount -o ro -t devtmpfs devtmpfs ${TARGET}/dev - chroot ${TARGET} passwd root - umount ${TARGET}/dev - else - chroot ${TARGET} passwd root - fi - else - passwd root - fi - fi - - echo "Refreshing snap" - - if [[ ${TARGET} ]]; then - chroot ${TARGET} snap refresh - else - snap refresh - fi - exit 0 - ;; - prerm) - exit 0 - ;; - postrm) - exit 0 - ;; -esac diff --git a/SRC/snap/Makefile.skel b/SRC/snap/Makefile.skel index b77a08e..d48eb17 100644 --- a/SRC/snap/Makefile.skel +++ b/SRC/snap/Makefile.skel @@ -19,7 +19,7 @@ ARCHIVE := $(PWD)/SRC/$(shell ls SRC|egrep '(bz2|gz|tar|xz)$$'|tail -1) TYPE := $(shell file -ib $(ARCHIVE)|cut -d';' -f1|tr -d '\n') SRCDIR := $(shell tar -tf $(ARCHIVE)|head -1|sed 's/\/.*//') PATCHDIR := $(PWD)/SRC/patches -VERSION := $(shell echo $(SRCDIR)|egrep -o '\-[0-9].*'|sed 's/^-//')$(SNAPVER) +VERSION := $(shell echo $(SRCDIR)|egrep -o '\-[0-9].*'|sed 's/^-//')-$(SNAPVER) include /usr/share/snap/Makefile.snaplinux diff --git a/SRC/snap/Makefile.snaplinux b/SRC/snap/Makefile.snaplinux index 8e0560d..2047008 100644 --- a/SRC/snap/Makefile.snaplinux +++ b/SRC/snap/Makefile.snaplinux @@ -13,7 +13,14 @@ PACKAGE := $(shell echo $(PWD)|sed 's/.*\///') SNAPDIR = $(PWD)/SNAP ROOT = $(PWD)/ROOT +# This allows the package Makefile to override the name +# of the package file. Added for the kernel package +# though could be useful for others + +ifeq ( $(SNAP), ) SNAP = $(PACKAGE)-$(VERSION).snap +endif + SNAPINFO = $(SNAPDIR)/snapinfo MANIFEST = $(SNAPDIR)/manifest USHER = $(SNAPDIR)/usher @@ -105,21 +112,19 @@ $(FILES): $(ROOT) done; \ fi - if [ "$(PACKAGE)" != 'grub' ]; then - @find $(ROOT) -type f | while read -r file; do \ - type=`file -i $$file|sed 's/.*: //'`; \ - case $$type in \ - *'/x-executable; charset=binary') \ - strip --strip-unneeded $$file \ - ;; \ - *'/x-object; charset=binary') \ - strip --strip-unneeded $$file \ - ;; \ - *'/x-sharedlib; charset=binary') \ - strip --strip-unneeded $$file \ - ;; \ - esac; \ - done; \ - fi + @find $(ROOT) -type f | while read -r file; do \ + type=`file -i $$file|sed 's/.*: //'`; \ + case $$type in \ + *'/x-executable; charset=binary') \ + strip --strip-unneeded $$file \ + ;; \ + *'/x-object; charset=binary') \ + strip --strip-debug $$file \ + ;; \ + *'/x-sharedlib; charset=binary') \ + strip --strip-debug $$file \ + ;; \ + esac; \ + done @cd $(ROOT) && tar cvzf $(FILES) * diff --git a/SRC/snap/Package.pm b/SRC/snap/Package.pm index d6fc60c..0aac645 100644 --- a/SRC/snap/Package.pm +++ b/SRC/snap/Package.pm @@ -255,7 +255,7 @@ sub depends { } ); if ( ! $package ) { - push( @$failures, $depend ); + push( @$failures, "$depend" ); next; } @@ -273,10 +273,9 @@ sub depends { } if ( @$failures ) { - print STDERR "Failed to resolve dependencies for" - . " $self->{'name'}!\n"; + print STDERR "Failed to resolve dependencies\n"; - Snap->error( -1, "depends(): dependencies failed: " + Snap->error( -1, "depends(): unresolved dependencies: " . join( ",", @$failures ) ); } @@ -402,7 +401,12 @@ sub install { my $stat; local $| = 1; - print "\e[?25lInstalling $self->{'name'}:\r"; + $ENV{'VERSION'} = $self->{'version'}; + + if ( ! -f $self->{'path'} ) { + Snap->error( -1, "install(): $self->{'path'}:" + . " No such file or directory" ); + } if ( $self->{'path'} =~ /^https*:\/\// ) { ( my $filename = $self->{'path'} ) =~ s/.*\///; @@ -443,13 +447,19 @@ sub install { Snap->error( int( $! ), "rename(): $manifest: $!" ); } + print "Installing $self->{'name'}=$self->{'version'}\n"; + $self->usher( 'preinst' ); + print "\e[?25l\r"; + eval { + my $target = Snap->TARGET || '/'; + $pid = open3( \*CHLDIN, \*CHLDOUT, \*CHLDERR, "/usr/bin/ar p $self->{'path'} files.tar.gz|" - . "tar --no-overwrite-dir -hzvxf - -C " - . Snap->TARGET ); + . "tar --no-overwrite-dir --keep-directory-symlink" + . " -hzvxf - -C $target" ); } || Snap->error( int( $! ), "open3(): /usr/bin/ar: $!" ); close( CHLDIN ); @@ -481,8 +491,7 @@ sub install { if ( $file ) { $cnt++; - print "\e[KInstalling " - . "$self->{'name'}: $file\r"; + print "\e[K$file\r"; } } elsif ( fileno( $fh ) == fileno( *CHLDERR ) ) { @@ -502,6 +511,8 @@ sub install { . " $stderr\e[?25h" ); } + print "\e[K$cnt files extracted\e[?25h\n"; + if ( $oldpkg ) { foreach ( @{$oldpkg->{'files'}} ) { if ( -f Snap->TARGET . "/$_" ) { @@ -548,7 +559,7 @@ sub install { Snap->error( int( $! ), "unlink(): $manifest: $!" ); } - print "\e[KInstalling $self->{'name'}: DONE\e[?25h\n"; + print "Finished installing $self->{'name'}\n"; } sub installed { @@ -741,7 +752,7 @@ sub usher { my $stderr; my $stat; - if ( ! -f $usher || $action eq 'preinst' ) { + if ( $action eq 'preinst' ) { my $cnt = 0; eval { @@ -769,17 +780,16 @@ sub usher { if ( fileno( $fh ) == fileno( *CHLDOUT ) ) { my $line = <$fh>; - if ( ! $cnt && $line =~ - /^no entry usher in archive$/ ) { - last; - } - print USHER $line; $cnt++; } elsif ( fileno( $fh ) == fileno( *CHLDERR ) ) { $stderr .= <$fh>; + + if ( $stderr =~ /^no entry usher/ ) { + last; + } } } } @@ -798,6 +808,8 @@ sub usher { if ( ! $cnt && -f $usher ) { unlink( $usher ); + + return; } } @@ -805,17 +817,17 @@ sub usher { return; } - eval { - $pid = open3( \*CHLDIN, \*CHLDOUT, \*CHLDERR, - "TARGET=" . Snap->TARGET . " $usher $action" ); - } || Snap->error( int( $! ), "open3():" - . " $usher ($action): $!" ); + if ( $pid = fork() ) { + waitpid( $pid, 0 ); + $stat = $? >> 8; + } + else { + exec( "$usher $action" ); + } - close( CHLDIN ); - - $sel = IO::Select->new(); - $sel->add( *CHLDOUT, *CHLDERR ); - $sel = IO::Select->new(); + if ( $stat ) { + Snap->error( $stat, "usher(): Failed executing usher" ); + } } ############################################################ diff --git a/SRC/snap/Snap.pm b/SRC/snap/Snap.pm index ca633f6..38d97f3 100644 --- a/SRC/snap/Snap.pm +++ b/SRC/snap/Snap.pm @@ -23,6 +23,7 @@ our @EXPORT = qw( human list listfiles + virtfs readconf refresh setup @@ -118,6 +119,8 @@ $0 =~ s/.*\///; ############################################################ $SIG{INT} = sub{ + virtfs( 'umount' ); + print "\e[?25h\n"; exit( -1 ); @@ -125,7 +128,7 @@ $SIG{INT} = sub{ ############################################################ # -# Export TARGET to the environment +# Export TARGET to the environment for usher # ############################################################ @@ -195,6 +198,8 @@ sub error { chomp( $errstr ); + print "\e[?25h\n"; + print STDERR ( caller() )[1] .":\n $errstr at line " . ( caller() )[2] . "\n"; @@ -212,6 +217,8 @@ sub error { print "\n"; if ( $status ) { + virtfs( 'umount' ); + exit( $status ); } } @@ -404,6 +411,26 @@ sub human { return( $human ); } +sub ismountpoint { + my $dir = shift; + my $statA; + my $statB; + + if ( ! -d $dir ) { + return( 0 ); + } + + $statA = ( stat( $dir ) )[0]; + $statB = ( stat( "$dir/.." ) )[0]; + + if ( $statA == $statB ) { + return( 0 ); + } + else { + return( 1 ); + } + } + sub list { my $packages = {}; my $package = {}; @@ -638,20 +665,50 @@ sub sha256 { } sub termsize { - require 'sys/ioctl.ph'; - my $data; - my $row; - my $col; + my $row = 24; + my $col = 80; + my $sel = IO::Select->new(); + my $stdout; + my $stderr; + my $stat; + my $pid; - open( TTY, "+error( 0, "No tty: $!" ); + eval { + $pid = open3( \*CHLDIN, \*CHLDOUT, \*CHLDERR, + "stty size -F /dev/tty" ); + } || return( { row => $row, col => $col } ); - if ( ! ioctl( TTY, &TIOCGWINSZ, $data='' ) ) { - Snap->error( 0, "Failed to determine window size" ); + close( CHLDIN ); + + $sel->add( *CHLDOUT, *CHLDERR ); + + while ( my @fhs = $sel->can_read ) { + foreach my $fh ( @fhs ) { + if ( eof( $fh ) ) { + $sel->remove( $fh ); + + next; + } + + if ( fileno( $fh ) == fileno( *CHLDOUT ) ) { + $stdout .= <$fh>; + } + elsif ( fileno( $fh ) == fileno( *CHLDERR ) ) { + $stderr .= <$fh>; + } + } } - close( TTY ); + close( CHLDOUT ); + close( CHLDERR ); - ( $row, $col ) = unpack( 'S4', $data ); + waitpid( $pid, 0 ); + $stat = $? >> 8; + + if ( $stdout =~ /(\d+)\s+(\d+)/ ) { + $row = $1; + $col = $2; + } return( { row => $row, col => $col } ); } @@ -732,4 +789,108 @@ sub vercmp { @A <=> @B; } +sub virtfs { + my $command = shift; + my $virtfs = { + dev => { + fs => 'devtmpfs', + dev => 'none', + dir => TARGET . '/dev' + }, + proc => { + fs => 'proc', + dev => 'none', + dir => TARGET . '/proc' + }, + sys => { + fs => 'sysfs', + dev => 'none', + dir => TARGET .'/sys' + } + }; + + if ( ! TARGET ) { + return; + } + + foreach my $fs ( sort( keys( %$virtfs ) ) ) { + my $sel; + my $cmd; + my $stdout = ''; + my $stderr = ''; + my $stat = 0; + my $pid; + + if ( ! -f $virtfs->{$fs}{'dir'} ) { + next; + } + + if ( $command eq 'mount' ) { + if ( ismountpoint( $virtfs->{$fs}{'dir'} ) ) { + next; + } + + $cmd = "mount -t $virtfs->{$fs}{'fs'}" + . " $virtfs->{$fs}{'dev'}" + . " $virtfs->{$fs}{'dir'}"; + } + elsif ( $command eq 'umount' ) { + if ( ! ismountpoint( $virtfs->{$fs}{'dir'} ) ) { + next; + } + + $cmd = "umount $virtfs->{$fs}{'dir'}"; + } + else { + Snap->error( -1, "virtfs(): $command:" + . " not a valid command" ); + } + + eval { + $pid = open3( \*CHLDIN, \*CHLDOUT, \*CHLDERR, $cmd ); + } || Snap->error( int( $! ), "open3(): $cmd: $!" ); + + close( CHLDIN ); + + $sel = IO::Select->new(); + $sel->add( *CHLDOUT, *CHLDERR ); + + while ( my @fhs = $sel->can_read ) { + foreach my $fh ( @fhs ) { + if ( eof( $fh ) ) { + $sel->remove( $fh ); + + next; + } + + if ( fileno( $fh ) == fileno( *CHLDOUT ) ) { + $stdout .= <$fh>; + } + elsif ( fileno( $fh ) == fileno( *CHLDERR ) ) { + $stderr .= <$fh>; + } + } + } + + close( CHLDOUT ); + close( CHLDERR ); + + waitpid( $pid, 0 ); + $stat = $? >> 8; + + if ( $stat ) { + Snap->error( $stat, "Failed $command for" + . " $virtfs->{$fs}{'dir'}: $stderr" ); + } + } + + foreach my $fs ( sort( keys( %$virtfs ) ) ) { + if ( ! ismountpoint( $virtfs->{$fs}{'dir'} ) ) { + return( 0 ); + } + } + + return( 1 ); + } + 1; diff --git a/SRC/snap/Sources.pm b/SRC/snap/Sources.pm index 266a848..5436875 100644 --- a/SRC/snap/Sources.pm +++ b/SRC/snap/Sources.pm @@ -219,7 +219,7 @@ sub search { if ( ! @$packages ) { if ( $opts->{'name'} && $opts->{'version'} ) { Snap->error( 0, "Snap::Sources::search():" - . " $opts->{'name'}=$opts->{'version'}:" + . " $opts->{'name'}$opts->{'version'}:" . " No such package" ); } elsif ( $opts->{'name'} ) { diff --git a/SRC/snap/snap b/SRC/snap/snap index c69350f..97b9a83 100755 --- a/SRC/snap/snap +++ b/SRC/snap/snap @@ -102,6 +102,7 @@ elsif ( $command eq 'install' ) { my $string = "@ARGV"; my $packages = []; my $bytes = 0; + my $virtfs = 0; foreach my $attrib ( @attribs ) { if ( $string =~ /$attrib\s*:\s*(\S+)/ ) { @@ -291,17 +292,31 @@ elsif ( $command eq 'install' ) { } } - print "\n\nInstall will require " . human( $bytes ) - . ". Continue? (y/n): "; + if ( $bytes < 0 ) { + print "\n\nInstall will recover " . human( -1 * $bytes ) + . ". Continue? (y/n): "; + } + else { + print "\n\nInstall will require " . human( $bytes ) + . ". Continue? (y/n): "; + } chkyes(); print "\n"; foreach my $package ( @$packages ) { + if ( ! $virtfs ) { + $virtfs = virtfs( 'mount' ); + } + $package->install( $sources ); } + if ( $virtfs ) { + virtfs( 'umount' ); + } + print "\n"; } elsif ( $command eq 'list' ) { @@ -498,35 +513,6 @@ elsif ( $command eq 'search' ) { exit -1; } - print "\n"; - } -elsif ( $command eq 'setup' ) { - my $opts = { - repo => 'core', - quiet => 1 - }; - my $packages; - - print "\n"; - - if ( ! Snap->TARGET ) { - Snap->error( -1, 'A target must be specified with -t' ); - } - - $sources->readpkgs(); - $packages = $sources->search( $opts ); - - for ( my $i = 0; $i <= $#$packages; $i++ ) { - if ( $packages->[$i]{'name'} eq 'snap-base' ) { - unshift( @$packages, $packages->[$i] ); - splice( @$packages, $i+1, 1 ); - } - } - - foreach my $package ( @$packages ) { - $package->install(); - } - print "\n"; } elsif ( $command eq 'verify' ) { diff --git a/SRC/snapinstall b/SRC/snapinstall new file mode 100755 index 0000000..d1bda7f --- /dev/null +++ b/SRC/snapinstall @@ -0,0 +1,89 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Snap; +use Data::Dumper; + +setup(); + +my $conf = readconf(); +my $sources = Snap::Sources->new( $conf->{'sources'} ); + +my $opts = { + repo => 'core', + quiet => 1 + }; +my $corepkgs; +my $packages; +my $virtfs = 0; +my $prepkgs = {}; +my $prelist = [ 'snap-base', 'bash', 'coreutils', 'glibc', + 'libacl', 'libattr', 'libcap', 'ncurses', 'readline', + 'tzdata', 'perl', 'initscripts' ]; + +print "\n"; + +if ( ! Snap->TARGET ) { + Snap->error( -1, 'A target must be specified with -t' ); + } + +$sources->readpkgs(); +$corepkgs = $sources->search( $opts ); + +for ( my $i = 0; $i <= $#$corepkgs; $i++ ) { + if ( ! $opts->{'nodeps'} ) { + print "Resolving dependencies for" + . " $corepkgs->[$i]{'name'}\n"; + + $corepkgs->[$i]->depends( $sources, $packages ); + } + else { + print "Ignoring dependencies for" + . " $corepkgs->[$i]{'name'}\n"; + } + + push( @$packages, $corepkgs->[$i] ); + } + +for ( my $i = 0; $i <= $#$packages; $i++ ) { + if ( $packages->[$i]{'path'} =~ /https*:\/\// ) { + ( my $filename = $packages->[$i]{'path'} ) =~ s/.*\///; + + if ( ! -f Snap->PKGDIR . "/$filename" ) { + Snap->httpget( $packages->[$i]{'path'}, + Snap->PKGDIR . "/$filename", 0644 ); + } + + $packages->[$i]{'path'} = Snap->PKGDIR . "/$filename"; + } + + + if ( grep( $_ eq $packages->[$i]{'name'}, @$prelist ) ) { + $prepkgs->{$packages->[$i]{'name'}} = $packages->[$i]; + + splice( @$packages, $i, 1 ); + $i--; + } + } + +foreach my $package ( @$prelist ) { + print "\n"; + + $prepkgs->{$package}->install(); + } + +foreach my $package ( @$packages ) { + if ( ! $virtfs ) { + $virtfs = virtfs( 'mount' ); + } + + print "\n"; + + $package->install(); + } + +virtfs( 'umount' ); + +print "\n";