[debian] Installing *.ipk/*.opk part 2: apt-get-file

Rask Ingemann Lambertsen rask at sygehus.dk
Sun May 10 17:51:06 CEST 2009


   For part 1, please see the mailing list archive:
http://lists.openmoko.org/pipermail/community/2009-March/043753.html

   Below you will find a shell script to install a package from a .deb, .opk
or .ipk file on a Debian system. It will

	- download the package if necessary.
	- repack gzipped tar archives if necessary (some *.ipk).
	- edit the control file for Debian compatibility (*.opk and *.ipk).
	- jump through hoops so apt-get can be used for installation,
	so dependencies can be resolved necessary.
	- delete all temporary files created.

   Dependencies: dpkg-dev wget file binutils tar gzip

   Usage: apt-get-file [--verbose] install <file> [apt-get options]

   I'm sure there are still small bugs around the edges, so this is only
alpha quality. I'm posting the script now because it mostly does what it's
supposed to do and I want to get some feedback.

   Example run:

# ~rask/bin/apt-get-file install http://projects.openmoko.org/frs/download.php/575/ledclock_0.6_all.ipk
--2009-05-10 06:49:26--  http://projects.openmoko.org/frs/download.php/575/ledclock_0.6_all.ipk
Resolving projects.openmoko.org... 88.198.93.218
Connecting to projects.openmoko.org|88.198.93.218|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 13214 (13K) [application/binary]
Saving to: `ledclock_0.6_all.ipk'

100%[================================================================>] 13,214      --.-K/s   in 0.1s    

2009-05-10 06:49:28 (99.5 KB/s) - `ledclock_0.6_all.ipk' saved [13214/13214]

 ** Packages in archive but missing from override file: **
  ledclock

 Wrote 1 entries to output Packages file.
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following extra packages will be installed:
  python-pygtk python-subprocess python2.6-minimal
Suggested packages:
  binfmt-support
Recommended packages:
  python2.6
The following NEW packages will be installed:
  ledclock python-pygtk python-subprocess python2.6-minimal
0 upgraded, 4 newly installed, 0 to remove and 112 not upgraded.
Need to get 1331kB/1344kB of archives.
After this operation, 4780kB of additional disk space will be used.
Do you want to continue [Y/n]? 
WARNING: The following packages cannot be authenticated!
  python-pygtk python-subprocess ledclock
Install these packages without verification [y/N]? y
Get:1 http://ftp.dk.debian.org experimental/main python2.6-minimal 2.6.1-3 [1330kB]
Get:2 http://nospamnospam.homepage.dk  python-pygtk 2.14.1-2 [576B]
Get:3 http://nospamnospam.homepage.dk  python-subprocess 2.6.1-3 [582B]
Fetched 1331kB in 2s (451kB/s)                                          
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously deselected package python-pygtk.
(Reading database ... 45694 files and directories currently installed.)
Unpacking python-pygtk (from .../python-pygtk_2.14.1-2_all.deb) ...
Selecting previously deselected package python2.6-minimal.
Unpacking python2.6-minimal (from .../python2.6-minimal_2.6.1-3_armel.deb) ...
Selecting previously deselected package python-subprocess.
Unpacking python-subprocess (from .../python-subprocess_2.6.1-3_all.deb) ...
Selecting previously deselected package ledclock.
Unpacking ledclock (from .../ledclock_0.6_all.deb) ...
Processing triggers for man-db ...
Setting up python-pygtk (2.14.1-2) ...
Setting up python2.6-minimal (2.6.1-3) ...
Could not find platform dependent libraries <exec_prefix>
Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
Setting up python-subprocess (2.6.1-3) ...
Setting up ledclock (0.6) ...
#

   And the script itself:

#!/bin/sh

# apt-get-file - Install package from .deb, .opk or .ipk file.
# Copyright (c) 2009 Rask Ingemann Lambertsen <ccc94453 at vip.cybercity.dk>

#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License version 3 as
#   published by the Free Software Foundation.

#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.

#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.

exit_clean () {
	cd / || true
	[ -z "${APTSRC}" ]	|| rm -rf -- "${APTSRC}"
	[ -z "${APTLIST}" ]	|| rm -rf -- "${APTLIST}"
	[ -z "${PKG_TMPDIR}" ]	|| rm -rf -- "${PKG_TMPDIR}"
	exit 1
}

trap exit_clean ERR
set -o errexit
set -o errtrace

if [ "--verbose" = "$1" ]; then
	shift
	AR_VERBOSE=v
	TAR_VERBOSE=v
	set -o xtrace
else
	AR_VERBOSE=
	TAR_VERBOSE=
fi

if [ "install" != "$1" ]; then
	echo "Usage: $0 [--verbose] install <file> <apt-get options>"
	exit 1
fi
shift

PKG_URL="$1"; shift
PKG_FILE=$(basename "${PKG_URL}")

case "${PKG_FILE}" in
	*.opk)
	PKG_FORMAT=opk
	;;
	*.deb)
	PKG_FORMAT=deb
	;;
	*)
	PKG_FORMAT=ipk
	;;
esac

PKG_TMPDIR=$(mktemp -d)
cd "${PKG_TMPDIR}" || exit $?

# A debian package file can be used directly, everything else
# needs a copy.
case "${PKG_URL}" in
	http://* | https://* | ftp://*)
	wget -O "${PKG_FILE}" -- "${PKG_URL}"
	;;
	*)
	PKG_URL=$(echo "${PKG_URL}" | sed -e 's/^file://')
	if [ "deb" = "${PKG_FORMAT}" ]; then
		ln -s "${PKG_URL}" "${PKG_FILE}" 
	else
		cp "${PKG_URL}" "${PKG_FILE}" 
	fi
	;;
esac

PKG_DEB=$(echo "${PKG_FILE}" | sed -e 's/\.[^.]*$/.deb/')
PKG_FILE_FORMAT=$(file --brief --dereference -- "${PKG_FILE}")

case "${PKG_FILE_FORMAT}" in
	"gzip compressed data"*)
	PKG_FORMAT=ipk
	;;
	"Debian binary package"*)
	if [ "ipk" = "${PKG_FORMAT}" ]; then
		PKG_FORMAT=opk
	fi
	;;
	*)
	echo "Unsupported package format ${PKG_FILE_FORMAT}.";
	exit 1
	;;
esac

# Unpack the package if not .deb format.
case "${PKG_FORMAT}" in
	ipk)
	tar -zx${TAR_VERBOSE}f "${PKG_FILE}"
	rm -f "${PKG_FILE}"
	;;
	opk)
	ar xo${AR_VERBOSE} "${PKG_FILE}" control.tar.gz
	mv "${PKG_FILE}" "${PKG_DEB}"
	;;
esac

# Debian uses architectures 'armel' and 'all'. There appears to
# be no way of telling dpkg/APT of compatible architectures.
# Edit the control file.
if [ "${PKG_FORMAT}" != "deb" ]; then
	mkdir control
	tar -C control -zx${TAR_VERBOSE}f control.tar.gz

	sed -i	-e 's/^Architecture: any$/Architecture: all/' \
		-e 's/^Architecture: \(armv[1234]t\?\|arm\|om-gta02\)$/Architecture: armel/' \
		control/control

	(cd control && tar -zc${TAR_VERBOSE}f ../control.tar.gz *)
fi

# Repack the .ipk or .opk package as .deb.
if [ "ipk" = "${PKG_FORMAT}" ]; then
	ar qc${AR_VERBOSE} "${PKG_DEB}" debian-binary control.tar.gz data.tar.gz
elif [ "opk" = "${PKG_FORMAT}" ]; then
	ar r${AR_VERBOSE} "${PKG_DEB}" control.tar.gz
fi

# What follows is an ugly hack, but you just can't pass a filename to
# apt-get. So fake a repository with the package in it and install it
# by package name.

# mktemp brain damage: You can't make a file ending in .list.
APTSRC=$(mktemp /etc/apt/sources.list.d/00-apt-get-file-XXXXXXXXXX)
ln "${APTSRC}" "${APTSRC}.list" && rm -f "${APTSRC}"
APTSRC="${APTSRC}.list"
echo "deb file:${PKG_TMPDIR}/ /" >"${APTSRC}"

APTLIST=/var/lib/apt/lists/$(echo "${PKG_TMPDIR}/Packages" | tr / _)
dpkg-scanpackages . /dev/null | sed -e 's_^Filename: ./_Filename: _' >"${APTLIST}"

PKG_NAME=$(dpkg-deb --field "${PKG_DEB}" Package)
apt-get install "$@" "${PKG_NAME}"

# Clean up.
cd /
rm -r -f -- "${APTSRC}" "${APTLIST}" "${PKG_TMPDIR}"


-- 
Rask Ingemann Lambertsen
Danish law requires addresses in e-mail to be logged and stored for a year




More information about the community mailing list