Anatomy of a Deb Package

Introduction

The Debian and Ubuntu distributions organize their software using deb packages. Debian has some fancy tools (debhelper) which help build these packages. This paper explains the structure of a deb package and shows that it is easy to build a deb package manually without using the debhelper tools.

Downloading a Package

Suppose you have a package installed called hello. You want to know where (what repository) that package came from. Use the apt-cache policy command like this:

bash$ apt-cache policy hello
hello:
  Installed: 2.2-2
  Candidate: 2.2-2
  Version table:
 *** 2.2-2 0
        500 http://ca.archive.ubuntu.com gutsy/main Packages
        100 /var/lib/dpkg/status

The important parts are the installed version number and the URL. The URL shows which repository it is from (ca.archive.ubuntu.com) and it's pocket and component (gutsy/main). But here is it's listing in /etc/apt/sources.list:

deb http://ca.archive.ubuntu.com/ubuntu/ gutsy main restricted

So you can see that the repository is actually at http://ca.archive.ubunu.com/ubuntu. So I cruise to that URL with firefox, go into the pool directory and eventually find the hello_2.2-2_i386.deb package:

http://ca.archive.ubuntu.com/ubuntu/pool/main/h/hello/hello_2.2-2_i386.deb

The ar Command

The deb file is an archive containing several files. You could think of it as a zip file, but debian doesn't use the zip utility. Instead, debian chose to use the old ar command from binutils. ar is most commonly used by programmers to combine several object files (for instance produced by gcc with suffix .o) into a single library file with the suffix .a. If you are a programmer and have a library file in one of your projects you can manipulate that file using the ar command. For instance, to look at a listing of the contents of the popular libvorbis.a library I can use the ar command with the -t switch:

bash$ ar -t /usr/lib/libvorbis.a
mdct.o
smallft.o
block.o
envelope.o
window.o
lsp.o
lpc.o
analysis.o
synthesis.o
psy.o
info.o
floor1.o
floor0.o
res0.o
mapping0.o
registry.o
codebook.o
sharedbook.o
lookup.o
bitrate.o

The old ar command can be used in a more general sense to create an archive of any type of file, but it has some limitations compared to zip. The two biggest limitations are:

  1. ar doesn't do compression
  2. ar doesn't store directory trees

So we create a temporary directory, move the hello package to the temporary directory, then extract it's contents using the ar command.

bash$ mkdir temp
bash$ mv hello* temp
bash$ cd temp
bash$ ar x hello*
bash$ ls
control.tar.gz  data.tar.gz  debian-binary  hello_2.2-2_i386.deb

The deb file contains three files: control.tar.gz, data.tar.gz, debian-binary.

debian-binary

The last file is just a text file containing the version number of the debian system, which at this time is 2.0:

bash$ cat debian-binary 
2.0

Of course, the control and data files are stored as tarballs because ar doesn't do compression or directory structures. So next unpack the tarballs

control.tar.gz

bash$ tar -xzvf control.tar.gz 
./
./control

The control file contains information that the debian needs to calculate dependencies and display information about the file. Here's a copy of the hello package control file:

bash$ cat control
Package: hello
Version: 2.2-2
Section: devel
Priority: optional
Architecture: i386
Depends: libc6 (>= 2.5-0ubuntu1)
Installed-Size: 584
Maintainer: Ubuntu Core Developers 
Original-Maintainer: Santiago Vila 
Description: The classic greeting, and a good example
 The GNU hello program produces a familiar, friendly greeting.  It
 allows non-programmers to use a classic computer science tool which
 would otherwise be unavailable to them.
 .
 Seriously, though: this is an example of how to do a Debian package.
 It is the Debian version of the GNU Project's `hello world' program
 (which is itself an example for the GNU Project).

Section 5.3 of the Debian Policy Manual specifies the fields of the control file.

data.tar.gz

The data tarball contains the actual files which we will install on the system, assuming that the current directory is root.

bash$ tar -xzvf data.tar.gz 
./
./usr/
./usr/share/
./usr/share/doc/
./usr/share/doc/hello/
./usr/share/doc/hello/NEWS
./usr/share/doc/hello/copyright
./usr/share/doc/hello/changelog.gz
./usr/share/doc/hello/changelog.Debian.gz
./usr/share/man/
./usr/share/man/man1/
./usr/share/man/man1/hello.1.gz
./usr/bin/
./usr/bin/hello

Easier to make Custom Packages Without Debhelper!

The ar tool is easy to use. The control file is well specified in the policy manual. It's easy to set up a directory structure for the binary files and make the tarball. On the otherhand, the debhelper tools are complicated and poorly documented. So I think it is actually easier to create custom packages by hand (or write a simple bash script) rather than use the debian packaging tools.