Author: elliss
Update of /cvs/docs/rpm-guide
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv860
Added Files:
rpm-guide-programming-c-en.xml
Log Message:
--- NEW FILE rpm-guide-programming-c-en.xml ---
<!-- $Id: -->
<chapter id="ch-programming-c">
<title>Programming RPM with C</title>
<para>
Copyright (c) 2005 by Eric Foster-Johnson. This material may be
distributed only subject to the terms and conditions set forth in
the Open Publication License, v1.0 or later (the latest version is
presently available at
http://www.opencontent.org/openpub/).
</para>
<para/>
<para>
In This Chapter
</para>
<para>
*Using the RPM C library
</para>
<para>
*Setting up a development environment
</para>
<para>
*Programming with the RPM C library
</para>
<para>
*The power of popt for command-line argument processing
</para>
<para>
*Comparing package files to installed packages
</para>
<para>
The RPM C library allows you to perform all the operations of the
rpm command from within your own C or C++ programs.
</para>
<para>
The reason is simple: The rpm command was created using the RPM
libraries. These same libraries are available for you to use in your
own programs.
</para>
<para>
The rpm command itself is quick and, for the most part, simple. So,
why would you want to write RPM programs?
</para>
<para>
There are many reasons, some of which are listed here:
</para>
<para>
*Speed: If you need to perform a task on many RPM files such as
verifying a large set of files, then performing the task from one
program will be a lot faster than launching the rpm command for each
file.
</para>
<para>
*Custom options: If you need to do something the rpm command doesn't
offer, or doesn't make easy, then you may want to write your own
program.
</para>
<para>
*Convenience: If you need to make many packages quickly, with custom
options, your best bet may be to create a program suited for your
tasks. Before doing this, though, be sure to look into whether
writing a shell script will handle your task adequately. You'll find
writing RPM shell scripts goes much faster than writing whole
programs.
</para>
<para>
*Installation programs: The Windows world has standardized on
graphical installation programs such as InstallShield or
InstallAnywhere. The RPM system, on the other hand, has focused on
automated installation with the rpm command. You can combine the
best of both worlds by writing a graphical installation program on
top of the RPM system.
</para>
<para>
*Integration with environments: You may want to better integrate RPM
with a Linux desktop environment such as GNOME or KDE.
</para>
<para>
*Working with other languages: This book covers programming RPM with
C, the core language for the library, as well as the Python and Perl
scripting languages. You can use the RPM library, though, to help
bind with other languages such as Tcl, Ruby, or even C# (especially
one of the C# implementations for Linux).
</para>
<para>
This chapter and the next cover RPM programming. This chapter covers
the RPM C programming library, which provides low-level access to
RPM functionality. The next chapter covers the RPM Python
programming library, which provides a much higher-level of
abstraction. If you are attempting to write a complex RPM program,
your best bet is to try the Python API first. Even so, there is a
lot you can do with the RPM C library.
</para>
<sect1>
<title>Programming with the C Library</title>
<para>
RPM C programs are C programs that call on functions in the RPM
library, often called rpmlib. To use the rpmlib, you need to set
up a C programming environment and install the rpm-devel package.
</para>
<sect2>
<title>Setting Up a C Programming Environment</title>
<para>
At the very least, you���ll need a C compiler, gcc, and a text
editor. The easiest way to get the C compiler is to install the
packages grouped under Software Development with the Red Hat
package management tool.
</para>
<para>
Cross Reference
</para>
<para>
See Chapter 8 for more on the Red Hat package management tool.
</para>
<para>
The gcc package requires a number of capabilities. Make sure you
install all the necessary packages. Just about every Linux
distribution includes gcc and everything you need to develop C
programs, so this should not be a problem.
</para>
<para>
For text editors, you can use the vi or emacs text editors, or
any of a number of graphical editors such as gedit.
</para>
<para>
Cross Reference
</para>
<para>
Appendix F covers Linux text editors and development tools.
</para>
<para>
Once you have a C programming environment set up, you next need
to get the RPM library for an RPM development environment.
</para>
</sect2>
<sect2>
<title>Setting Up the RPM Programming Environment</title>
<para>
To program with the RPM library, you need to install the
rpm-devel package. You must have a version of rpm-devel that
matches your version of the rpm package. If you have Red Hat
Linux, your installation CDs will also have the version of the
RPM development package that corresponds to your system.
</para>
<para>
Your program should link against the same libraries that are
used by the rpm command itself in order to insure compatibility,
so make sure that the version of the rpm-devel package matches
the rpm package itself. In most cases, the best bet is to use
the RPM programs and libraries that come with your version of
Linux.
</para>
<para>
Cross Reference
</para>
<para>
You can also download the rpm packages from
ftp://ftp.rpm.org/pub/rpm/dist/. This site includes versions of
the RPM libraries going back to 1996, ancient history in terms
of Linux.
</para>
<para>
The package you need is rpm-devel. If you installed Red Hat
Linux 8.0, the package is rpm-devel-4.1-1.06. This package
includes header files, documentation, and libraries.
</para>
</sect2>
<sect2>
<title>Using the RPM Library</title>
<para>
All C programs using the RPM library need to include the file
rpmlib.h, which defines the core data structures, constants, and
functions. One thing you���ll quickly note is that the RPM C
library accesses RPM data at a very low level. This is one
reason why many developers are moving to Python for their RPM
programs, since the Python RPM API presents a higher level of
abstraction.
</para>
<para>
Cross Reference
</para>
[...3592 lines suppressed...]
<para/>
<para>
ts = rpmtsCreate();
</para>
<para/>
<para>
/* Check for query mode. */
</para>
<para>
if (qva->qva_mode == 'q') {
</para>
<para>
/* Make sure there's something to do. */
</para>
<para>
if (qva->qva_source != RPMQV_ALL &&
!poptPeekArg(context)) {
</para>
<para>
fprintf(stderr, "no arguments given for --query");
</para>
<para>
exit(EXIT_FAILURE);
</para>
<para>
}
</para>
<para/>
<para>
ec = rpmcliQuery(ts, qva, (const char **) poptGetArgs(context));
</para>
<para>
}
</para>
<para>
/* Check for verify mode. */
</para>
<para>
else if (qva->qva_mode == 'V') {
</para>
<para>
rpmVerifyFlags verifyFlags = VERIFY_ALL;
</para>
<para/>
<para>
/* Verify flags are negated from query flags. */
</para>
<para>
verifyFlags &= ~qva->qva_flags;
</para>
<para>
qva->qva_flags = (rpmQueryFlags) verifyFlags;
</para>
<para/>
<para>
/* Make sure there's something to do. */
</para>
<para>
if (qva->qva_source != RPMQV_ALL &&
!poptPeekArg(context)) {
</para>
<para>
fprintf(stderr, "no arguments given for --verify");
</para>
<para>
exit(EXIT_FAILURE);
</para>
<para>
}
</para>
<para/>
<para>
ec = rpmcliVerify(ts, qva, (const char **) poptGetArgs(context));
</para>
<para>
}
</para>
<para>
else {
</para>
<para>
poptPrintUsage(context, stderr, 0);
</para>
<para>
exit(EXIT_FAILURE);
</para>
<para>
}
</para>
<para/>
<para>
ts = rpmtsFree(ts);
</para>
<para/>
<para>
context = rpmcliFini(context);
</para>
<para/>
<para>
return ec;
</para>
<para>
}
</para>
<para>
There is not a lot of code in rpmq.c, as this program is mostly
calling the high-level functions for the rpm command-line
interface.
</para>
<para>
When you run the rpmq program, it performs the same tasks as the
rpm command with the --query (or -q) and --verify (or -V)
command-line options.
</para>
<para>
For example, rpmq supports query formats:
</para>
<para>
$ ./rpmq -q --qf "%{NAME} %{INSTALLTID:date}\n" jikes
</para>
<para>
jikes Fri 25 Oct 2002 06:49:38 PM CDT
</para>
</sect1>
<sect1>
<title>Where to Go from Here</title>
<para>
There is a lot more you can do with the RPM library; you're
limited only by your imagination. The best way to get started is
to follow the examples in this chapter and then try out some RPM
programs on your own. After working with the RPM library for a
while, you can delve into other RPM topics.
</para>
<para>
The RPM Web site, at
www.rpm.org, has most of the available
documentation on the RPM system. This site also includes official
RPM released software.
</para>
<para>
One of the best ways to help find out about how to perform RPM
tasks is to look at the source code for the rpm program itself.
For this, download the rpm-src source RPM, too. To see the rpm
command-line interface functions in action, look especially at
tools/rpmcache.c and tools/rpmgraph.c, two relatively short RPM
files that show how to take advantage of a number of short cuts.
The source code for the Python and Perl bindings can also provide
extra hints about the purposes of the RPM API calls.
</para>
<para>
The RPM Web site also has a cross-referenced set of HTML pages on
the RPM programming API. The pages for version 4.1 of RPM are
available at
www.rpm.org/rpmapi-4.1/. A good starting page is
www.rpm.org/rpmapi-4.1/modules.html, which lists a number of
modules within the overall RPM library. This extra level of
organization can help you locate the functions you need.
</para>
</sect1>
<sect1>
<title>Summary</title>
<para>
Everything you can do with RPM you can program in C. That���s
because the source code for the entire RPM system is available. In
addition, the rpm and rpmbuild programs make use of a published
API, called rpmlib, to access RPM functionality. You can use this
library yourself.
</para>
<para>
The popt library, short for parse options, provides a lot of handy
utilities for parsing very complex command-line options. You can
use popt inside your own programs, even if you don���t use the
rest of the RPM functionality.
</para>
<para>
Most RPM programs start up by calling rpmcliInit, which sets up
RPM variables for the large set of command-line options supported
by most RPM commands.
</para>
<para>
Call rpmReadPackageFile to read in the Header object from a
package file. You can also get Header objects for the packages
installed in a system by initializing an iterator to iterate over
a set of packages that meet a certain criteria.
</para>
<para>
This chapter covers a fairly low level of access to RPM
functionality. The next chapter, on Python programming, shows a
higher level of abstraction for working with RPM.
</para>
</sect1>
</chapter>
<!--
Local variables:
mode: xml
sgml-parent-document:("rpm-guide-en.xml" "book" "chapter")
fill-column: 72
End:
-->