# HG changeset patch
# User Dan Drake
# Date 1268121405 -32400
# Node ID ea75176adb6fadbe18e981235e37b7221d066ba1
# Parent 69ccc5d679b1e1c42e57b28e492770cfd185040a
integrity verification for spkgs; see trac #329
diff --git a/sage-add-integrity-check-to-spkg b/sage-add-integrity-check-to-spkg
new file mode 100755
--- /dev/null
+++ b/sage-add-integrity-check-to-spkg
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+
+# given a spkg file as $1, this adds the necessary checksum information.
+# See http://trac.sagemath.org/sage_trac/ticket/329.
+
+SPKGNAME=$(basename $1 .spkg)
+
+if [ "x$1" = "x$SPKGNAME" ]
+then
+ echo "I don't think you gave me a spkg file."
+ exit 1
+fi
+
+echo Adding integrity verification checksum to $1...
+
+# is the spkg bzipped?
+TYPE=$(file $1 | grep 'bzip2 compressed data')
+if [ -z "$TYPE" ]
+then
+ CAT="cat"
+ UNCAT="cat"
+else
+ CAT="bunzip2 -c"
+ UNCAT="bzip2 -c"
+fi
+
+$CAT $1 > $SPKGNAME.tar
+
+(tar xf $SPKGNAME.tar --exclude $SPKGNAME.cksum -O; \
+tar tvf $SPKGNAME.tar --exclude $SPKGNAME.cksum) | \
+cksum | awk '{print $1, $2}' > $SPKGNAME.cksum
+
+echo checksum of $1 is `cat $SPKGNAME.cksum`.
+
+tar rf $SPKGNAME.tar $SPKGNAME.cksum
+
+$UNCAT $SPKGNAME.tar > $1
+rm $SPKGNAME.tar $SPKGNAME.cksum
diff --git a/sage-spkg b/sage-spkg
--- a/sage-spkg
+++ b/sage-spkg
@@ -216,6 +216,8 @@
cd "$CUR"
fi
+sage-spkg-integrity-check $PKG_SRC
+
# * The -i option below to ignore checksum errors, since
# I've had problems with this on Solaris.
# * The m option avoids clock skew problems.
diff --git a/sage-spkg-integrity-check b/sage-spkg-integrity-check
new file mode 100755
--- /dev/null
+++ b/sage-spkg-integrity-check
@@ -0,0 +1,68 @@
+#!/usr/bin/env bash
+
+# Given a spkg file as $1, this script will check the integrity of $1
+# using the methods descrbed in
+# http://trac.sagemath.org/sage_trac/ticket/329.
+#
+# This script exits with status...
+# 0 if the verification passed;
+# 1 if the checksum exits but verification failed;
+# 2 if no cksum information was found;
+# 3 if something else goes wrong.
+
+if [ -z "$1" ]
+then
+ echo Error in $0: you need to specify a .spkg file.
+ exit 3
+fi
+
+if [ -z "$SAGE_ROOT" ]
+then
+ echo Error in $0: \$SAGE_ROOT must be set.
+ exit 3
+fi
+
+echo -n "Verifying integrity of $1..."
+
+SPKGNAME=$(basename $1 .spkg)
+
+# is the spkg bzipped?
+TYPE=$(file $1 | grep 'bzip2 compressed data')
+if [ -z "$TYPE" ]
+then
+ J=""
+else
+ # we're assuming that "j" is the tar option for bzip2 compression
+ J="j"
+fi
+
+# extract existing checksum
+tar ${J}xf $1 -O $SPKGNAME.cksum | awk 'NR==1 {print $1, $2}' > $SAGE_ROOT/spkg/cksum/$SPKGNAME.downloaded.cksum
+
+# the "NR==1" tells awk to only print line 1; if a checksum gets put
+# into the spkg twice, the -O in tar will print it out twice. We just
+# take the first line.
+
+# GNU tar exits with exit code 2 if the file isn't found, so we use the
+# bash PIPESTATUS array to check that exit code (the usual $? returns
+# the exit code of the final process in the pipe)
+if [ ${PIPESTATUS[0]} = "2" ]
+then
+ echo no integrity checksum stored in $1, skipping integrity check.
+ exit 2
+fi
+
+# now compute the checksum
+(tar ${J}xf $1 -O --exclude $SPKGNAME.cksum ; \
+tar ${J}tvf $1 --exclude $SPKGNAME.cksum 2>/dev/null) | \
+cksum | awk '{print $1, $2}' > $SAGE_ROOT/spkg/cksum/$SPKGNAME.computed.cksum
+
+cmp $SAGE_ROOT/spkg/cksum/$SPKGNAME.downloaded.cksum $SAGE_ROOT/spkg/cksum/$SPKGNAME.computed.cksum
+if [ $? = "0" ]
+then
+ echo passed.
+else
+ echo FAILED!
+ echo $1 appears corrupted; expected checksum is \"$(cat $SAGE_ROOT/spkg/cksum/$SPKGNAME.downloaded.cksum)\", but computed checksum is \"$(cat $SAGE_ROOT/spkg/cksum/$SPKGNAME.computed.cksum)\".
+ exit 1
+fi