📄 0330-0333.html
字号:
<HTML>
<HEAD>
<TITLE>Maximum RPM (RPM):A Guide to the RPM Library API:EarthWeb Inc.-</TITLE>
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<SCRIPT>
<!--
function displayWindow(url, width, height) {
var Win = window.open(url,"displayWindow",'width=' + width +
',height=' + height + ',resizable=1,scrollbars=yes');
}
//-->
</SCRIPT>
</HEAD>
-->
<!-- ISBN=0672311054 //-->
<!-- TITLE=Maximum RPM (RPM)//-->
<!-- AUTHOR=Edward Bailey//-->
<!-- PUBLISHER=Macmillan Computer Publishing//-->
<!-- IMPRINT=Sams//-->
<!-- CHAPTER=21 //-->
<!-- PAGES=0305-0336 //-->
<!-- UNASSIGNED1 //-->
<!-- UNASSIGNED2 //-->
<P><CENTER>
<a href="0326-0329.html">Previous</A> | <a href="../ewtoc.html">Table of Contents</A> | <a href="0334-0336.html">Next</A>
</CENTER></P>
</PRE><A NAME="PAGENUM-330"><P>Page 330</P></A>
<P>This loop uses headerNextIterator() to return each entry's tag, type, data, and size. By
using a switch statement on the tag, we can perform different operations on each type of entry in
the header:
</P>
<!-- CODE //-->
<PRE>
while (headerNextIterator(iter, &itertag, &type, p, &count)) {
switch (itertag) {
case RPMTAG_SUMMARY:
blather = *p;
printf("The Summary: %s\n", blather);
break;
case RPMTAG_FILENAMES:
printf("There are %d files in this package\n", count);
break;
}
</PRE>
<!-- END CODE //-->
<P>This is the housecleaning section of the program. First we free the iterator that we've been
using, and finally the header itself:
</P>
<!-- CODE //-->
<PRE>
}
headerFreeIterator(iter);
headerFree(h);
}
</PRE>
<!-- END CODE //-->
<P>Running this program on a package gives us the following output:
</P>
<!-- CODE //-->
<PRE>
# ./dump amanda-client-2.3.0-2.i386.rpm
There is a postinstall script for amanda-client
Dumping signatures...
Entry count: 2
Data count : 20
CT TAG TYPE OFSET COUNT
Entry : 000 (1000)NAME INT32_TYPE 0x00000000 00000001
Data: 000 0x00029f5d (171869)
Entry : 001 (1003)SERIAL BIN_TYPE 0x00000004 00000016
Data: 000 27 01 f9 97 d8 2c 36 40
Data: 008 c6 4a 91 45 32 13 d1 62
Iterating through the header...
The Summary: Client-side Amanda package
There are 11 files in this package
#
</PRE>
<!-- END CODE //-->
<H4>
21.3.2. Example #2
</H4>
<P>This example delves a bit more into the database-related side of rpmlib. After initializing
rpmlib's variables by reading the appropriate
rpmrc files, the code traverses the database records,
looking for a specific package. That package's header is then dumped in its entirety.
</P>
<P>As before, this is the normal way of including all of rpmlib's definitions:
</P>
<!-- CODE SNIP //-->
<PRE>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
</PRE>
<!-- END CODE SNIP //--><A NAME="PAGENUM-331"><P>Page 331</P></A><!-- CODE SNIP //-->
<PRE>
#include <unistd.h>
#include <stdlib.h>
#include <rpm/rpmlib.h>
</PRE>
<!-- END CODE SNIP //-->
<P>Here are the data declarations. Note the declaration of
db; this is how we will be accessing the RPM database:
</P>
<!-- CODE //-->
<PRE>
void main(int argc, char ** argv)
{
Header h;
int offset;
int dspBlockNum = 0; /* default to all */
int blockNum = 0;
int_32 type, count;
char * name;
rpmdb db;
</PRE>
<!-- END CODE //-->
<P>Before opening the RPM database, it's necessary to know where the database resides. This
information is stored in rpmrc files, which are read by
rpmReadConfigFiles(). To show that this function is really doing its job, we retrieve the RPM database path before and after the
rpmrc files are read. Note that we test the return value of
rpmGetVar(RPM_DBPATH) and, if it is null, we insert
(none) in the printf() output. This prevents possible core dumps if no database
path has been set; and besides, it's more user friendly:
</P>
<!-- CODE //-->
<PRE>
printf("The database path is: %s\n",
rpmGetVar(RPMVAR_DBPATH) ? rpmGetVar(RPM_DBPATH) : "(none)");
rpmReadConfigFiles(NULL, NULL, NULL, 0);
printf("The database path is: %s\n",
rpmGetVar(RPMVAR_DBPATH) ? rpmGetVar(RPM_DBPATH) : "(none)");
</PRE>
<!-- END CODE //-->
<P>Here we're opening the RPM database and doing some cursory error checking to make
sure we should continue:
</P>
<!-- CODE //-->
<PRE>
if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) {
fprintf(stderr, "cannot open /var/lib/rpm/packages.rpm\n");
exit(1);
}
</PRE>
<!-- END CODE //-->
<P>We get the offset of the first database record:
</P>
<!-- CODE SNIP //-->
<PRE>
offset = rpmdbFirstRecNum(db);
</PRE>
<!-- END CODE SNIP //-->
<P>Here we start a while loop based on the record offset. As long as there is a non-zero
offset (meaning that there is still an available record), we get the record. If there's a problem
getting the record, we exit:
</P>
<!-- CODE //-->
<PRE>
while (offset) {
h = rpmdbGetRecord(db, offset);
if (!h) {
fprintf(stderr, "headerRead failed\n");
exit(1);
}
</PRE>
<!-- END CODE //--><A NAME="PAGENUM-332"><P>Page 332</P></A>
<P>Next, we get the package name entry from the record and compare it with the name of
the package we're interested in. If it matches, we dump the contents of the entire record:
</P>
<!-- CODE SNIP //-->
<PRE>
headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count);
if (strcmp(name, argv[1]) == 0)
headerDump(h, stdout, 1);
</PRE>
<!-- END CODE SNIP //-->
<P>At the end of the loop, we free the record and get the offset to the next record:
</P>
<!-- CODE SNIP //-->
<PRE>
headerFree(h);
offset = rpmdbNextRecNum(db, offset);
}
</PRE>
<!-- END CODE SNIP //-->
<P>At the end, we close the database and exit:
</P>
<!-- CODE SNIP //-->
<PRE>
rpmdbClose(db);
}
</PRE>
<!-- END CODE SNIP //-->
<P>Here's the program's output, edited for brevity (notice that the database path changes
from (null) to /var/lib/rpm after the rpmrc files are read):
</P>
<!-- CODE //-->
<PRE>
# ./showdb amanda-client
The database path is: (null)
The database path is: /var/lib/rpm
Entry count: 37
Data count : 5219
CT TAG TYPE OFSET COUNT
Entry : 000 (1000)NAME STRING_TYPE 0x00000000 00000001
Data: 000 amanda-client
Entry : 001 (1001)VERSION STRING_TYPE 0x0000000e 00000001
Data: 000 2.3.0
Entry : 002 (1002)RELEASE STRING_TYPE 0x00000014 00000001
Data: 000 7
Entry : 003 (1004)SUMMARY STRING_TYPE 0x00000016 00000001
Data: 000 Client-side Amanda package
Entry : 004 (1005)DESCRIPTION STRING_TYPE 0x00000031 00000001
...
Entry : 017 (1027)FILENAMES STRING_ARRAY_TYPE 0x00000df3 00000015
Data: 000 /usr/doc/amanda-client-2.3.0-7
Data: 001 /usr/doc/amanda-client-2.3.0-7/COPYRIGHT
Data: 002 /usr/doc/amanda-client-2.3.0-7/INSTALL
Data: 003 /usr/doc/amanda-client-2.3.0-7/README
Data: 004 /usr/doc/amanda-client-2.3.0-7/SYSTEM.NOTES
Data: 005 /usr/doc/amanda-client-2.3.0-7/WHATS.NEW
Data: 006 /usr/doc/amanda-client-2.3.0-7/amanda-client.README
...
Entry : 034 (1049)REQUIRENAME STRING_ARRAY_TYPE 0x0000141c 00000006
Data: 000 libc.so.5
Data: 001 libdb.so.2
Data: 002 grep
Data: 003 sed
Data: 004 NetKit-B
Data: 005 dump
...
#
</PRE>
<!-- END CODE //--><A NAME="PAGENUM-333"><P>Page 333</P></A>
<P>As you can see, everything that you could possibly want to know about an installed package
is available using this method.
</P>
<H4>
21.3.3. Example #3
</H4>
<P>This example is similar in function to the previous one, except that it uses rpmlib's search
functions to find the desired package record. Here we include rpmlib's definitions:
</P>
<!-- CODE //-->
<PRE>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <rpm/rpmlib.h>
</PRE>
<!-- END CODE //-->
<P>Here are the storage declarations:
</P>
<!-- CODE SNIP //-->
<PRE>
void main(int argc, char ** argv)
{
Header h;
int stat;
rpmdb db;
dbiIndexSet matches;
</PRE>
<!-- END CODE SNIP //-->
<P>In this section, we do some argument processing, process the
rpmrc files, and open the RPM database:
</P>
<!-- CODE //-->
<PRE>
if (argc != 2) {
fprintf(stderr, "showdb2 <search term>\n");
exit(1);
}
rpmReadConfigFiles(NULL, NULL, NULL, 0);
if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) {
fprintf(stderr, "cannot open /var/lib/rpm/packages.rpm\n");
exit(1);
}
</PRE>
<!-- END CODE //-->
<P>In this section, we use rpmdbFindPackage() to search for the desired package:
</P>
<!-- CODE //-->
<PRE>
stat = rpmdbFindPackage(db, argv[1], &matches);
printf("Status is: %d\n", stat);
if (stat == 0) {
if (matches.count) {
printf("Number of matches: %d\n", matches.count);
h = rpmdbGetRecord(db, matches.recs[0].recOffset);
if (h) headerDump(h, stdout, 1);
headerFree(h);
dbiFreeIndexRecord(matches);
}
}
</PRE>
<P><CENTER>
<a href="0326-0329.html">Previous</A> | <a href="../ewtoc.html">Table of Contents</A> | <a href="0334-0336.html">Next</A>
</CENTER></P>
</td>
</tr>
</table>
<!-- begin footer information -->
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -