#!/bin/sh
# makeslapt - make a slapt-get compatible slackware package
# by Eko M. Budi
#
# The original code was included in checkinstall as makepak,
# which in turn was from Slakware's makepak
#
# ----------------------------------------------------------------
# Copyright 1994, 1998 Patrick Volkerding, Moorhead, Minnesota USA
# Copyright 2003 Slackware Linux, Inc. Concord, CA USA
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Wed Mar 18 15:32:33 CST 1998
# Patched to avoid possible symlink attacks in /tmp.
#
# Sat Dec 09 2000 - Felipe Sanchez <izto@asic-linux.com.mx>
# Removed the code for the questions about symlinks and sane permissions
# They are useless to CheckInstall
#
# Fri Jul 20 2001 - Felipe Sanchez <izto@asic-linux.com.mx>
# Included the patch made to makepkg in the Slackware 8.0 release.
#
# Aug, 2004 = Eko M. Budi
# patch to simplify symlinks creation using readlink (needs coreutil 5.0 up)
# add symlinks to the preexisting doinst.sh (assume it was created by checkinstall)
#
# Oct, 2004 = Eko M. Budi
# Add dependency tracking for slapt-get
#
# Nov, 2004 = Eko M. Budi, the Dumb Bunny revealed
# Fix tar silly ./ problem
#
# Nov, 2004 = Eko M. Budi & Jason Woodward
# Fix package name function
#
# Nov, 2004 = Eko M. Budi, the Dumber Bunny revealed
# Refix tar silly ./ problem. DOH !!!
# Her ya her ya ... Use the old tar-1.13 !!
#
# Dec, 2004 = Eko M. Budi
# Checkinstall 1.6.0beta4 out, always want to pass options ...
# So combine the original makepkg from Slackware 10
# Renamed to makeslapt, to make it clear
#
# March, 2006 = Eko M. Budi
# - Use 2 digit max dependency rule
# (e.g: gtk2+ >= 2.6.8 became gtk2+ >= 2.6)
# - Add lib_with_path() patch by YaP
# - support tgz, tbz, or tlz format
TAR=tar-1.13
umask 022
$TAR --help 1> /dev/null 2> /dev/null
if [ ! $? = 0 ]; then
TAR=tar
fi
if [ ! "`LC_MESSAGES=C $TAR --version`" = "tar (GNU tar) 1.13
Copyright (C) 1988, 92,93,94,95,96,97,98, 1999 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by John Gilmore and Jay Fenlason." ]; then
echo "WARNING: pkgtools are unstable with tar > 1.13."
echo " You should provide a \"tar-1.13\" in your \$PATH."
sleep 5
fi
usage() {
cat << EOF
Usage: makeslapt [options] package_name.tgz
Makes a Slackware compatible package containing the contents of the
current and all subdirectories. If symbolic links exist, they will be
removed and a doinst.sh script will be made to recreate them later.
It also generates dependency rules for slapt-get, named slack-required.
The default format is tgz, you may change it to tbz or tlz format
by using command line option (-g, -b, -l), or export PKGFORMAT
enviromental variable PKGFORMAT, e.g :
export PKGFORMAT=tlz
options:
-s, --slapt y|n add slapt-get dependency info, default Y
-f, --full y|n add full dependency info, default Y
-l, --linkadd y|n moves symlinks into doinst.sh, default Y.
-p, --prepend add symlinks to the front of the existing doinst.sh.
-c, --chown y|n resets all permissions to root:root 755, default N
-g, --tgz use tgz format (default)
-b, --tbz use tbz format
-l, --tlz use tlz format
EOF
}
# Return package name, from Jason
# This is fast, but DOES NOT WORK if the package does not follow
# standard package naming, notably VERSION with -, e.g:
# xine-lib-1-rc1-i486-1 --> return xine-lib-1
# In that case, replace '-' with '_'.
pkgname() {
echo $1 | sed -re "s/(.*{1,})\\-(.*[\\.\\-].*[\\.\\-].*)[ ]{0,}$/\1/"
}
# return package name, orthodox way
# Not used anymore because the reg-exp way is faster
# although this Orthodox way can handle nasty name better
# put bad guy names here
KNOWN_NAMES="cdparanoia slib libjpeg"
KNOWN_ARCHS="noarch i386 i486 i586 i686 i786 i886 i986"
pkgname1() {
name=${1%%-*}
ver_rest=${1#$name-}
while [ 0 ]; do
## 1st rule, if known name then that's it !
if echo "$KNOWN_NAMES " | grep -q "$name "; then
break
fi
## 2nd rule, if digits followed by . or - then stop
if echo $ver_rest | grep -qe "^[0-9]*[\.\-_]"; then
break
fi
## 3rd, if the next segment is known architecture, stop
extra=${ver_rest%%-*}
ver_rest=${ver_rest#$extra-}
if echo "$KNOWN_ARCHS " | grep -q `echo $ver_rest | cut -f1 -d-`; then
break
fi
## 4rd, no more rest, then break
if [ "$ver_rest" = "$extra" ]; then
break
fi
## concat the name then continue
name="${name}-${extra}"
done
echo $name
}
## Insert dependency info ala slapt-get
## The autodependency is generated using ldd ala swaret
## Let them fight as they like, we are free to get the best of them :)
REQUIRED=install/slack-required
DESCRIPTION=install/slack-desc
## Add dependency info if not exist yet
add_required()
{
if ! grep -qw "$1" $REQUIRED 2>/dev/null; then
if [ "$SLAPT_FULL" = "y" ] && [ "$3" ]; then
# trying to find the lesser version
REQ_VERSION=${3%%_*}
REQ_VERSION=`echo $REQ_VERSION | cut -f 1-2 -d '.'`
echo "$*" >> $REQUIRED
echo "$*"
else
echo "$1" >> $REQUIRED
echo "$1"
fi
fi
}
## find dependency
find_required()
{
## if $2 not null, assume it is a complete requirement
if [ "$2" ]; then
add_required $*
return 0
fi
## try to find version info from the installed packages
DDNAME=$1
if ls /var/log/packages/$DDNAME-* &>/dev/null; then
for DD in /var/log/packages/$DDNAME-* ; do
DDBASE=`basename $DD`
if [ "$DDNAME" = "`pkgname $DDBASE`" ]; then
DDVERSION=${DDBASE#${DDNAME}-}
# Left only version
DDVERSION=${DDVERSION%%-*}
add_required $DDNAME '>=' $DDVERSION
return 0
fi
done
fi
## Can't find version info, just add it then
add_required $DDNAME
}
# contributed by YaP
function lib_with_path()
{
LIB="$1"
if [ "${LIB:0:1}" == "/" ]; then
echo "${LIB:1}"
return 1
fi
if [ -f "/lib/$LIB" ]; then
echo "lib/$LIB"
return 1;
fi
if [ -f "/usr/lib/$LIB" ]; then
echo "usr/lib/$LIB"
return 1;
fi
cat /etc/ld.so.conf | while read PATH_LINE; do
LIBPATH="$PATH_LINE/$LIB"
if [ -f "$LIBPATH" ]; then
echo "${LIBPATH:1}"
return 0
fi
done
echo "$LIB"
return 1
}
function add_dependency()
{
# find the executables and track the required packages
find . -perm +1 ! -path './install/*' -print | while read LINE; do
[ ! -f "$LINE" ] && continue
[ ".${LINE##*.}" = ".la" ] && continue
echo "$LINE:"
if ! ldd "$LINE" &>/dev/null; then
# not a dynamic, possibly script
FTYPE=`file "$LINE"`
if echo $FTYPE | grep -q "Bourne" ; then
find_required bash
elif echo $FTYPE | grep -q "C shell" ; then
find_required tcsh
elif echo $FTYPE | grep -iqw "perl" ; then
find_required perl
elif echo $FTYPE | grep -iqw "python" ; then
find_required python
elif echo $FTYPE | grep -iqw "ruby" ; then
find_required ruby
elif echo $FTYPE | grep -iqw "php" ; then
find_required php
elif echo $FTYPE | grep -qw "tcl"; then
find_required tcl
elif echo $FTYPE | grep -qw "expect"; then
find_required expect
find_required tclx
find_required tcl
else
echo "WARNING: unknown dependency for $LINE"
fi
else
ldd $LINE | while read LINE1; do
LIB=`echo $LINE1 | cut -f1 -d ' '`
# SELF=$(find -name `basename $LIB`)
SELF=$(find -name `basename "$LIB*"`)
[ "$SELF" ] && continue
LIB="`lib_with_path $LIB`"
grep "$LIB" /var/log/packages/* | while read LINE2; do
DFULL=`echo $LINE2 | cut -f1 -d:`
DBASE=`basename $DFULL`
DNAME=`pkgname $DBASE`
case "$DNAME" in
aaa_elflibs|$PNAME)
continue
;;
esac
DVERSION=${DBASE#${DNAME}-}
DVERSION=${DVERSION%%-*}
add_required $DNAME '>=' $DVERSION
break
done
if [ $? != 0 ]; then
echo "WARNING : Cannot find dependency for $LIB"
fi
done
fi
done
}
function add_doinst() {
echo "Moving symbolic links to scripts ..."
# Using readlink to read the link, works with coreutils (Slackware 9.1 up).
# Old method using ls -l was broken since coreutil 5.0
find . -type l -print | while read LINE; do
DIRNAME="`dirname $LINE`"
LINKNAME="`basename $LINE`"
LINKTO="`readlink $LINE`"
echo "( cd $DIRNAME ; rm -rf $LINKNAME )" >> install/doinst.sh
echo "( cd $DIRNAME ; ln -sf $LINKTO $LINKNAME )" >> install/doinst.sh
rm -fv $LINE
done
}
# Default options
LINKADD=y
PREPEND=y
CHOWN=n
SLAPT=y
SLAPT_FULL=y
PKGFORMAT=${PKGFORMAT:-tgz}
# Parse options
while [ 0 ]; do
if [ "$1" = "--linkadd" -o "$1" = "-l" ]; then
if [ "$2" = "y" ]; then
LINKADD=y
elif [ "$2" = "n" ]; then
LINKADD=n
else
usage
exit 2
fi
shift 2
elif [ "$1" = "--chown" -o "$1" = "-c" ]; then
if [ "$2" = "y" ]; then
CHOWN=y
elif [ "$2" = "n" ]; then
CHOWN=n
else
usage
exit 2
fi
shift 2
elif [ "$1" = "--slapt" -o "$1" = "-s" ]; then
if [ "$2" = "y" ]; then
SLAPT=y
elif [ "$2" = "n" ]; then
SLAPT=n
else
usage
exit 2
fi
shift 2
elif [ "$1" = "--full" -o "$1" = "-f" ]; then
if [ "$2" = "y" ]; then
SLAPT_FULL=y
elif [ "$2" = "n" ]; then
SLAPT_FULL=n
else
usage
exit 2
fi
shift 2
elif [ "$1" = "-p" -o "$1" = "--prepend" ]; then
PREPEND=y
shift 1
elif [ "$1" = "-g" -o "$1" = "--tgz" ]; then
PKGFORMAT=tgz
shift 1
elif [ "$1" = "-b" -o "$1" = "--tbz" ]; then
PKGFORMAT=tbz
shift 1
elif [ "$1" = "-l" -o "$1" = "--tlz" ]; then
PKGFORMAT=tlz
shift 1
elif [ "$1" = "-h" -o "$1" = "-H" -o "$1" = "--help" -o $# = 0 ]; then
usage
exit 0
else
break
fi
done
echo
echo "Slackware SLAPT-GET package maker, version 2.1."
PACKAGE_NAME=$1
PDIR=`dirname $PACKAGE_NAME`
PLONG=`basename $PACKAGE_NAME`
PSHORT=${PLONG%.*}
PEXT=${PLONG##*.}
PNAME=`pkgname $PLONG`
mkdir -p install
if [ "$LINKADD" = "y" ]; then
if [ "$PREPEND" = "y" ]; then
echo "Prepending doins script ..."
touch install/doinst.sh
mv install/doinst.sh install/doinst.sh.shipped
echo "#!/bin/sh" > install/doinst.sh
add_doinst
echo "" >> install/doinst.sh
cat install/doinst.sh.shipped >> install/doinst.sh
rm -f install/doinst.sh.shipped
else
echo "Concatenating doinst script ..."
echo "" >> install/doinst.sh
add_doinst
fi
fi
if [ "$CHOWN" = "y" ]; then
echo "Fixing permission ..."
find . -type d -exec chmod -v 755 {} \;
find . -type d -exec chown -v root.root {} \;
fi
## Add dependency
if [ "$SLAPT" = "y" ]; then
echo "Adding slapt-get dependencies ..."
add_dependency
fi
## Add description, if not yet
if [ ! -f install/slack-desc ]; then
echo "$PNAME: $PNAME" > install/slack-desc
fi
echo
echo "Creating package $PSHORT.$PKGFORMAT ..."
# Don't be a dumb bunny, TAR must be tar-1.13
# With newer tar, these are broken:
# tar czvf $PACKAGE_NAME . --> creates leading ./, though fixable by installpkg
# tar czvf $PACKAGE_NAME * --> no leading ./, but installpkg will be confused
echo
echo "Creating tar file $PSHORT.tar..."
echo
$TAR cvf $PSHORT.tar .
# Warn of zero-length files:
find . -type f -size 0c | while read file ; do
echo "WARNING: zero length file $file"
done
find . -type f -name '*.gz' -size 20c | while read file ; do
echo "WARNING: possible empty gzipped file $file"
done
# packing the tar file into tgz, tlz, or tbz
echo
echo "Compressing $PSHORT.$PKGFORMAT ..."
case $PKGFORMAT in
tgz)
gzip -9 $PSHORT.tar
mv $PSHORT.tar.gz ${PDIR}/${PSHORT}.${PKGFORMAT}
;;
tlz)
lzma -7 $PSHORT.tar
mv $PSHORT.tar.lzma ${PDIR}/${PSHORT}.${PKGFORMAT}
;;
tbz)
bzip2 -9 $PSHORT.tar
mv $PSHORT.tar.bz2 ${PDIR}/${PSHORT}.${PKGFORMAT}
;;
esac
echo
echo "Package creation $PSHORT.$PEXT complete."
echo
if [ "$PEXT" != "$PKGFORMAT" ]; then
echo "WARNING: The package format is not the same as the given name."
echo "Please check the options or PKGFORMAT enviromental variable"
fi