libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

rpmlibex.html (20687B)


      1 <HTML
      2 ><HEAD
      3 ><TITLE
      4 >Example Code</TITLE
      5 ><META
      6 NAME="GENERATOR"
      7 CONTENT="Modular DocBook HTML Stylesheet Version 1.59"><LINK
      8 REL="HOME"
      9 TITLE="Maximum RPM"
     10 HREF="index.html"><LINK
     11 REL="UP"
     12 TITLE="A Guide to the RPM Library API"
     13 HREF="ch-rpm-rpmlib.html"><LINK
     14 REL="PREVIOUS"
     15 TITLE="rpmlib Functions"
     16 HREF="s1-rpm-rpmlib-functions.html"><LINK
     17 REL="NEXT"
     18 TITLE="      Appendixes
     19     "
     20 HREF="p13740.html"></HEAD
     21 ><BODY
     22 CLASS="SECT1"
     23 BGCOLOR="#FFFFFF"
     24 TEXT="#000000"
     25 LINK="#0000FF"
     26 VLINK="#840084"
     27 ALINK="#0000FF"
     28 ><DIV
     29 CLASS="NAVHEADER"
     30 ><TABLE
     31 WIDTH="100%"
     32 BORDER="0"
     33 CELLPADDING="0"
     34 CELLSPACING="0"
     35 ><TR
     36 ><TH
     37 COLSPAN="3"
     38 ALIGN="center"
     39 >Maximum RPM: Taking the Red Hat Package Manager to the Limit</TH
     40 ></TR
     41 ><TR
     42 ><TD
     43 WIDTH="10%"
     44 ALIGN="left"
     45 VALIGN="bottom"
     46 ><A
     47 HREF="s1-rpm-rpmlib-functions.html"
     48 >Prev</A
     49 ></TD
     50 ><TD
     51 WIDTH="80%"
     52 ALIGN="center"
     53 VALIGN="bottom"
     54 >Chapter 21. A Guide to the RPM Library API</TD
     55 ><TD
     56 WIDTH="10%"
     57 ALIGN="right"
     58 VALIGN="bottom"
     59 ><A
     60 HREF="p13740.html"
     61 >Next</A
     62 ></TD
     63 ></TR
     64 ></TABLE
     65 ><HR
     66 ALIGN="LEFT"
     67 WIDTH="100%"></DIV
     68 ><DIV
     69 CLASS="SECT1"
     70 ><H1
     71 CLASS="SECT1"
     72 ><A
     73 NAME="S1-RPM-RPMLIB-EXAMPLE-CODE"
     74 >Example Code</A
     75 ></H1
     76 ><P
     77 >        In this section, we'll study example programs that make use of rpmlib to
     78         perform an assortment of commonly-required operations.
     79       </P
     80 ><DIV
     81 CLASS="SECT2"
     82 ><H2
     83 CLASS="SECT2"
     84 ><A
     85 NAME="S2-RPM-RPMLIB-EXAMPLE1"
     86 >Example #1</A
     87 ></H2
     88 ><P
     89 >          In this example, we'll use a number of rpmlib's header manipulation
     90           functions.
     91 
     92           <TABLE
     93 BORDER="0"
     94 BGCOLOR="#E0E0E0"
     95 WIDTH="100%"
     96 ><TR
     97 ><TD
     98 ><PRE
     99 CLASS="SCREEN"
    100 ><TT
    101 CLASS="COMPUTEROUTPUT"
    102 >#include &#60;errno.h&#62;
    103 #include &#60;fcntl.h&#62;
    104 #include &#60;stdio.h&#62;
    105 #include &#60;unistd.h&#62;
    106 #include &#60;string.h&#62;
    107 
    108 #include &#60;rpm/rpmlib.h&#62;</TT
    109 >
    110           </PRE
    111 ></TD
    112 ></TR
    113 ></TABLE
    114 >
    115         </P
    116 ><P
    117 >          Here we've included <TT
    118 CLASS="FILENAME"
    119 >rpmlib.h</TT
    120 >, which is necessary
    121           for all programs that use rpmlib.
    122 
    123           <TABLE
    124 BORDER="0"
    125 BGCOLOR="#E0E0E0"
    126 WIDTH="100%"
    127 ><TR
    128 ><TD
    129 ><PRE
    130 CLASS="SCREEN"
    131 ><TT
    132 CLASS="COMPUTEROUTPUT"
    133 >void main(int argc, char ** argv)
    134 {
    135   HeaderIterator iter;
    136     Header h, sig;
    137     int_32 itertag, type, count;
    138     void **p = NULL;
    139     char *blather;
    140     char * name;
    141 
    142     int fd, stat;</TT
    143 >
    144           </PRE
    145 ></TD
    146 ></TR
    147 ></TABLE
    148 >
    149         </P
    150 ><P
    151 >          Here we've defined the program's storage.  Note in particular the
    152           <SPAN
    153 CLASS="STRUCTNAME"
    154 >HeaderIterator</SPAN
    155 >,
    156           <SPAN
    157 CLASS="STRUCTNAME"
    158 >Header</SPAN
    159 >, and <SPAN
    160 CLASS="STRUCTNAME"
    161 >int_32</SPAN
    162 >
    163           datatypes.
    164 
    165           <TABLE
    166 BORDER="0"
    167 BGCOLOR="#E0E0E0"
    168 WIDTH="100%"
    169 ><TR
    170 ><TD
    171 ><PRE
    172 CLASS="SCREEN"
    173 ><TT
    174 CLASS="COMPUTEROUTPUT"
    175 >    if (argc == 1) {
    176         fd = 0;
    177     } else {
    178         fd = open(argv[1], O_RDONLY, 0644);
    179     }
    180 
    181     if (fd &#60; 0) {
    182         perror("open");
    183         exit(1);
    184     }</TT
    185 >
    186           </PRE
    187 ></TD
    188 ></TR
    189 ></TABLE
    190 >
    191         </P
    192 ><P
    193 >          Standard stuff here.  The first argument is supposed to be an RPM
    194           package file.  It is opened here.  If there is no argument on the
    195           command line, the program will use stdin instead.
    196 
    197           <TABLE
    198 BORDER="0"
    199 BGCOLOR="#E0E0E0"
    200 WIDTH="100%"
    201 ><TR
    202 ><TD
    203 ><PRE
    204 CLASS="SCREEN"
    205 ><TT
    206 CLASS="COMPUTEROUTPUT"
    207 >    stat = rpmReadPackageInfo(fd, &#38;sig, &#38;h);
    208     if (stat) {
    209       fprintf(stderr,
    210               "rpmReadPackageInfo error status: %d\n%s\n",
    211               stat, strerror(errno));
    212         exit(stat);
    213     }</TT
    214 >
    215           </PRE
    216 ></TD
    217 ></TR
    218 ></TABLE
    219 >
    220         </P
    221 ><P
    222 >          Here things start to get interesting!  The signature and headers are
    223           read from package file that was just opened.  If you noticed above,
    224           we've defined <TT
    225 CLASS="PARAMETER"
    226 ><I
    227 >sig</I
    228 ></TT
    229 > and <TT
    230 CLASS="PARAMETER"
    231 ><I
    232 >h</I
    233 ></TT
    234 >
    235           to be of type <SPAN
    236 CLASS="STRUCTNAME"
    237 >Header</SPAN
    238 >.  That means we can use
    239           rpmlib's header-related functions on them.  After a little bit of
    240           error checking, and it's time to move on&#8230;
    241 
    242           <TABLE
    243 BORDER="0"
    244 BGCOLOR="#E0E0E0"
    245 WIDTH="100%"
    246 ><TR
    247 ><TD
    248 ><PRE
    249 CLASS="SCREEN"
    250 ><TT
    251 CLASS="COMPUTEROUTPUT"
    252 >    headerGetEntry(h, RPMTAG_NAME, &#38;type, (void **) &#38;name, &#38;count);
    253 
    254     if (headerIsEntry(h, RPMTAG_PREIN)) {
    255         printf("There is a preinstall script for %s\n", name);
    256     }
    257 
    258     if (headerIsEntry(h, RPMTAG_POSTIN)) {
    259         printf("There is a postinstall script for %s\n", name);
    260     }</TT
    261 >
    262           </PRE
    263 ></TD
    264 ></TR
    265 ></TABLE
    266 >
    267         </P
    268 ><P
    269 >          Now that we have the package's header, we get the package name
    270           (specified by the <SPAN
    271 CLASS="SYMBOL"
    272 >RPMTAG_NAME</SPAN
    273 > above).  Next, we see
    274           if the package has pre-install (<SPAN
    275 CLASS="SYMBOL"
    276 >RPMTAG_PREIN</SPAN
    277 >) or
    278           post-install (<SPAN
    279 CLASS="SYMBOL"
    280 >RPMTAG_POSTIN</SPAN
    281 >) scripts.  If there are,
    282           we print out a message, along with the package name.
    283 
    284           <TABLE
    285 BORDER="0"
    286 BGCOLOR="#E0E0E0"
    287 WIDTH="100%"
    288 ><TR
    289 ><TD
    290 ><PRE
    291 CLASS="SCREEN"
    292 ><TT
    293 CLASS="COMPUTEROUTPUT"
    294 >    printf("Dumping signatures...\n");
    295     headerDump(sig, stdout, 1);
    296 
    297     rpmFreeSignature(sig);</TT
    298 >
    299           </PRE
    300 ></TD
    301 ></TR
    302 ></TABLE
    303 >
    304         </P
    305 ><P
    306 >          Turning to the other <SPAN
    307 CLASS="STRUCTNAME"
    308 >Header</SPAN
    309 > structure we've
    310           read, we print out the package's signatures in human-readable form.
    311           When we're done, we free the block of signatures.
    312 
    313           <TABLE
    314 BORDER="0"
    315 BGCOLOR="#E0E0E0"
    316 WIDTH="100%"
    317 ><TR
    318 ><TD
    319 ><PRE
    320 CLASS="SCREEN"
    321 ><TT
    322 CLASS="COMPUTEROUTPUT"
    323 >    printf("Iterating through the header...\n");
    324 
    325     iter = headerInitIterator(h);</TT
    326 >
    327           </PRE
    328 ></TD
    329 ></TR
    330 ></TABLE
    331 >
    332         </P
    333 ><P
    334 >          Here we set up an iterator for the package's header.  This will allow
    335           us to step through each entry in the header.
    336 
    337           <TABLE
    338 BORDER="0"
    339 BGCOLOR="#E0E0E0"
    340 WIDTH="100%"
    341 ><TR
    342 ><TD
    343 ><PRE
    344 CLASS="SCREEN"
    345 ><TT
    346 CLASS="COMPUTEROUTPUT"
    347 >    while (headerNextIterator(iter, &#38;itertag, &#38;type, p, &#38;count)) {
    348       switch (itertag) {
    349       case RPMTAG_SUMMARY:
    350         blather = *p;
    351         printf("The Summary: %s\n", blather);
    352         break;
    353       case RPMTAG_FILENAMES:
    354         printf("There are %d files in this package\n", count);
    355         break;
    356       }</TT
    357 >
    358           </PRE
    359 ></TD
    360 ></TR
    361 ></TABLE
    362 >
    363         </P
    364 ><P
    365 >          This loop uses <TT
    366 CLASS="FUNCTION"
    367 >headerNextIterator()</TT
    368 > to return
    369           each entry's tag, type, data, and size.  By using a
    370           <B
    371 CLASS="COMMAND"
    372 >switch</B
    373 > statement on the tag, we can perform
    374           different operations on each type of entry in the header.
    375 
    376           <TABLE
    377 BORDER="0"
    378 BGCOLOR="#E0E0E0"
    379 WIDTH="100%"
    380 ><TR
    381 ><TD
    382 ><PRE
    383 CLASS="SCREEN"
    384 ><TT
    385 CLASS="COMPUTEROUTPUT"
    386 >    }
    387 
    388     headerFreeIterator(iter);
    389 
    390     headerFree(h);
    391 
    392 }</TT
    393 >
    394           </PRE
    395 ></TD
    396 ></TR
    397 ></TABLE
    398 >
    399         </P
    400 ><P
    401 >          This is the housecleaning section of the program.  First we free the
    402           iterator that we've been using, and finally the header itself.
    403           Running this program on a package gives us the following output:
    404 
    405           <TABLE
    406 BORDER="0"
    407 BGCOLOR="#E0E0E0"
    408 WIDTH="100%"
    409 ><TR
    410 ><TD
    411 ><PRE
    412 CLASS="SCREEN"
    413 ><TT
    414 CLASS="PROMPT"
    415 ># </TT
    416 ><TT
    417 CLASS="USERINPUT"
    418 ><B
    419 >./dump amanda-client-2.3.0-2.i386.rpm</B
    420 ></TT
    421 >
    422 <TT
    423 CLASS="COMPUTEROUTPUT"
    424 >There is a postinstall script for amanda-client
    425 Dumping signatures...
    426 Entry count: 2
    427 Data count : 20
    428 
    429              CT  TAG                  TYPE           OFSET      COUNT
    430 Entry      : 000 (1000)NAME           INT32_TYPE     0x00000000 00000001
    431        Data: 000 0x00029f5d (171869)
    432 Entry      : 001 (1003)SERIAL         BIN_TYPE       0x00000004 00000016
    433        Data: 000 27 01 f9 97 d8 2c 36 40 
    434        Data: 008 c6 4a 91 45 32 13 d1 62 
    435 Iterating through the header...
    436 The Summary: Client-side Amanda package
    437 There are 11 files in this package</TT
    438 >
    439 <TT
    440 CLASS="PROMPT"
    441 ># </TT
    442 >
    443           </PRE
    444 ></TD
    445 ></TR
    446 ></TABLE
    447 >
    448         </P
    449 ></DIV
    450 ><DIV
    451 CLASS="SECT2"
    452 ><H2
    453 CLASS="SECT2"
    454 ><A
    455 NAME="S2-RPM-RPMLIB-EXAMPLE2"
    456 >Example #2</A
    457 ></H2
    458 ><P
    459 >          This example delves a bit more into the database-related side of
    460           rpmlib.  After initializing rpmlib's variables by reading the
    461           appropriate <TT
    462 CLASS="FILENAME"
    463 >rpmrc</TT
    464 > files, the code traverses the
    465           database records, looking for a specific package.  That package's
    466           header is then dumped in its entirety.
    467 
    468           <TABLE
    469 BORDER="0"
    470 BGCOLOR="#E0E0E0"
    471 WIDTH="100%"
    472 ><TR
    473 ><TD
    474 ><PRE
    475 CLASS="SCREEN"
    476 ><TT
    477 CLASS="COMPUTEROUTPUT"
    478 >#include &#60;errno.h&#62;
    479 #include &#60;fcntl.h&#62;
    480 #include &#60;stdio.h&#62;
    481 #include &#60;string.h&#62;
    482 #include &#60;unistd.h&#62;
    483 #include &#60;stdlib.h&#62;
    484 
    485 #include &#60;rpm/rpmlib.h&#62;</TT
    486 >
    487           </PRE
    488 ></TD
    489 ></TR
    490 ></TABLE
    491 >
    492         </P
    493 ><P
    494 >          As before, this is the normal way of including all of rpmlib's
    495           definitions.
    496 
    497           <TABLE
    498 BORDER="0"
    499 BGCOLOR="#E0E0E0"
    500 WIDTH="100%"
    501 ><TR
    502 ><TD
    503 ><PRE
    504 CLASS="SCREEN"
    505 ><TT
    506 CLASS="COMPUTEROUTPUT"
    507 >void main(int argc, char ** argv)
    508 {
    509     Header h;
    510     int offset;
    511     int dspBlockNum = 0;                /* default to all */
    512     int blockNum = 0;
    513     int_32 type, count;
    514     char * name;
    515     rpmdb db;</TT
    516 >
    517           </PRE
    518 ></TD
    519 ></TR
    520 ></TABLE
    521 >
    522         </P
    523 ><P
    524 >          Here are the data declarations.  Note the declaration of
    525           <TT
    526 CLASS="PARAMETER"
    527 ><I
    528 >db</I
    529 ></TT
    530 >: this is how we will be accessing the RPM
    531           database.
    532 
    533           <TABLE
    534 BORDER="0"
    535 BGCOLOR="#E0E0E0"
    536 WIDTH="100%"
    537 ><TR
    538 ><TD
    539 ><PRE
    540 CLASS="SCREEN"
    541 ><TT
    542 CLASS="COMPUTEROUTPUT"
    543 >    printf("The database path is: %s\n",
    544         rpmGetVar(RPMVAR_DBPATH) ? rpmGetVar(RPM_DBPATH) : "(none)");
    545 
    546     rpmReadConfigFiles(NULL, NULL, NULL, 0);
    547 
    548     printf("The database path is: %s\n",
    549         rpmGetVar(RPMVAR_DBPATH) ? rpmGetVar(RPM_DBPATH) : "(none)");</TT
    550 >
    551           </PRE
    552 ></TD
    553 ></TR
    554 ></TABLE
    555 >
    556         </P
    557 ><P
    558 >          Before opening the RPM database, it's necessary to know where the
    559           database resides.  This information is stored in
    560           <TT
    561 CLASS="FILENAME"
    562 >rpmrc</TT
    563 > files, which are read by
    564           <TT
    565 CLASS="FUNCTION"
    566 >rpmReadConfigFiles()</TT
    567 >.  To show that this function
    568           is really doing its job, we retrieve the RPM database path before and
    569           after the <TT
    570 CLASS="FILENAME"
    571 >rpmrc</TT
    572 > files are read.  Note that we
    573           test the return value of <TT
    574 CLASS="FUNCTION"
    575 >rpmGetVar(RPM_DBPATH)</TT
    576 >
    577           and, if it is null, we insert <TT
    578 CLASS="COMPUTEROUTPUT"
    579 >(none)</TT
    580 >
    581           in the <TT
    582 CLASS="FUNCTION"
    583 >printf()</TT
    584 > output.  This prevents possible
    585           core dumps if no database path has been set, and besides, it's more
    586           user-friendly.
    587 
    588           <TABLE
    589 BORDER="0"
    590 BGCOLOR="#E0E0E0"
    591 WIDTH="100%"
    592 ><TR
    593 ><TD
    594 ><PRE
    595 CLASS="SCREEN"
    596 ><TT
    597 CLASS="COMPUTEROUTPUT"
    598 >    if (rpmdbOpen("", &#38;db, O_RDONLY, 0644) != 0) {
    599         fprintf(stderr, "cannot open /var/lib/rpm/packages.rpm\n");
    600         exit(1);
    601     }</TT
    602 >
    603           </PRE
    604 ></TD
    605 ></TR
    606 ></TABLE
    607 >
    608         </P
    609 ><P
    610 >          Here we're opening the RPM database, and doing some cursory error
    611           checking to make sure we should continue.
    612 
    613           <TABLE
    614 BORDER="0"
    615 BGCOLOR="#E0E0E0"
    616 WIDTH="100%"
    617 ><TR
    618 ><TD
    619 ><PRE
    620 CLASS="SCREEN"
    621 ><TT
    622 CLASS="COMPUTEROUTPUT"
    623 >    offset = rpmdbFirstRecNum(db);</TT
    624 >
    625           </PRE
    626 ></TD
    627 ></TR
    628 ></TABLE
    629 >
    630         </P
    631 ><P
    632 >          We get the offset of the first database record&#8230;
    633 
    634           <TABLE
    635 BORDER="0"
    636 BGCOLOR="#E0E0E0"
    637 WIDTH="100%"
    638 ><TR
    639 ><TD
    640 ><PRE
    641 CLASS="SCREEN"
    642 ><TT
    643 CLASS="COMPUTEROUTPUT"
    644 >    while (offset) {
    645 
    646         h = rpmdbGetRecord(db, offset);
    647         if (!h) {
    648                 fprintf(stderr, "headerRead failed\n");
    649         exit(1);
    650                 }</TT
    651 >
    652           </PRE
    653 ></TD
    654 ></TR
    655 ></TABLE
    656 >
    657         </P
    658 ><P
    659 >          Here we start a <B
    660 CLASS="COMMAND"
    661 >while</B
    662 > loop based on the record
    663           offset.  As long as there is a non-zero offset (meaning that there is
    664           still an available record), we get the record.  If there's a problem
    665           getting the record, we exit.
    666 
    667           <TABLE
    668 BORDER="0"
    669 BGCOLOR="#E0E0E0"
    670 WIDTH="100%"
    671 ><TR
    672 ><TD
    673 ><PRE
    674 CLASS="SCREEN"
    675 ><TT
    676 CLASS="COMPUTEROUTPUT"
    677 >            headerGetEntry(h, RPMTAG_NAME, &#38;type, (void **) &#38;name, &#38;count);
    678             if (strcmp(name, argv[1]) == 0)
    679               headerDump(h, stdout, 1);</TT
    680 >
    681           </PRE
    682 ></TD
    683 ></TR
    684 ></TABLE
    685 >
    686         </P
    687 ><P
    688 >          Next, we get the package name entry from the record, and compare it
    689           with the name of the package we're interested in.  If it matches, we
    690           dump the contents of the entire record.
    691 
    692           <TABLE
    693 BORDER="0"
    694 BGCOLOR="#E0E0E0"
    695 WIDTH="100%"
    696 ><TR
    697 ><TD
    698 ><PRE
    699 CLASS="SCREEN"
    700 ><TT
    701 CLASS="COMPUTEROUTPUT"
    702 >        headerFree(h);
    703     
    704         offset = rpmdbNextRecNum(db, offset);
    705     }</TT
    706 >
    707           </PRE
    708 ></TD
    709 ></TR
    710 ></TABLE
    711 >
    712         </P
    713 ><P
    714 >          At the end of the loop, we free the record, and get the offset to the
    715           next record.
    716 
    717           <TABLE
    718 BORDER="0"
    719 BGCOLOR="#E0E0E0"
    720 WIDTH="100%"
    721 ><TR
    722 ><TD
    723 ><PRE
    724 CLASS="SCREEN"
    725 ><TT
    726 CLASS="COMPUTEROUTPUT"
    727 >&#13;    rpmdbClose(db);
    728 }</TT
    729 >
    730           </PRE
    731 ></TD
    732 ></TR
    733 ></TABLE
    734 >
    735         </P
    736 ><P
    737 >          At the end, we close the database, and exit.
    738         </P
    739 ><P
    740 >          Here's the program's output, edited for brevity.  Notice that the
    741           database path changes from <TT
    742 CLASS="COMPUTEROUTPUT"
    743 >(null)</TT
    744 > to
    745           <TT
    746 CLASS="FILENAME"
    747 >/var/lib/rpm</TT
    748 > after the <TT
    749 CLASS="FILENAME"
    750 >rpmrc</TT
    751 >
    752           files are read.
    753 
    754           <TABLE
    755 BORDER="0"
    756 BGCOLOR="#E0E0E0"
    757 WIDTH="100%"
    758 ><TR
    759 ><TD
    760 ><PRE
    761 CLASS="SCREEN"
    762 ><TT
    763 CLASS="PROMPT"
    764 ># </TT
    765 ><TT
    766 CLASS="USERINPUT"
    767 ><B
    768 >./showdb amanda-client</B
    769 ></TT
    770 >
    771 <TT
    772 CLASS="COMPUTEROUTPUT"
    773 >The database path is: (null)
    774 The database path is: /var/lib/rpm
    775 Entry count: 37
    776 Data count : 5219
    777 
    778              CT  TAG                  TYPE               OFSET      COUNT
    779 Entry      : 000 (1000)NAME        STRING_TYPE        0x00000000 00000001
    780        Data: 000 amanda-client
    781 Entry      : 001 (1001)VERSION     STRING_TYPE        0x0000000e 00000001
    782        Data: 000 2.3.0
    783 Entry      : 002 (1002)RELEASE     STRING_TYPE        0x00000014 00000001
    784        Data: 000 7
    785 Entry      : 003 (1004)SUMMARY     STRING_TYPE        0x00000016 00000001
    786        Data: 000 Client-side Amanda package
    787 Entry      : 004 (1005)DESCRIPTION STRING_TYPE        0x00000031 00000001
    788 &#8230;
    789 Entry      : 017 (1027)FILENAMES   STRING_ARRAY_TYPE  0x00000df3 00000015
    790        Data: 000 /usr/doc/amanda-client-2.3.0-7
    791        Data: 001 /usr/doc/amanda-client-2.3.0-7/COPYRIGHT
    792        Data: 002 /usr/doc/amanda-client-2.3.0-7/INSTALL
    793        Data: 003 /usr/doc/amanda-client-2.3.0-7/README
    794        Data: 004 /usr/doc/amanda-client-2.3.0-7/SYSTEM.NOTES
    795        Data: 005 /usr/doc/amanda-client-2.3.0-7/WHATS.NEW
    796        Data: 006 /usr/doc/amanda-client-2.3.0-7/amanda-client.README
    797 &#8230;
    798 Entry      : 034 (1049)REQUIRENAME STRING_ARRAY_TYPE  0x0000141c 00000006
    799        Data: 000 libc.so.5
    800        Data: 001 libdb.so.2
    801        Data: 002 grep
    802        Data: 003 sed
    803        Data: 004 NetKit-B
    804        Data: 005 dump
    805 &#8230;</TT
    806 >
    807 <TT
    808 CLASS="PROMPT"
    809 >#</TT
    810 >
    811           </PRE
    812 ></TD
    813 ></TR
    814 ></TABLE
    815 >
    816         </P
    817 ><P
    818 >          As can be seen, everything that you could possibly want to know about
    819           an installed package is available using this method.
    820         </P
    821 ></DIV
    822 ><DIV
    823 CLASS="SECT2"
    824 ><H2
    825 CLASS="SECT2"
    826 ><A
    827 NAME="S2-RPM-RPMLIB-EXAMPLE3"
    828 >Example #3</A
    829 ></H2
    830 ><P
    831 >          This example is similar in function to the previous one, except that
    832           it uses rpmlib's search functions to find the desired package record:
    833 
    834           <TABLE
    835 BORDER="0"
    836 BGCOLOR="#E0E0E0"
    837 WIDTH="100%"
    838 ><TR
    839 ><TD
    840 ><PRE
    841 CLASS="SCREEN"
    842 ><TT
    843 CLASS="COMPUTEROUTPUT"
    844 >#include &#60;errno.h&#62;
    845 #include &#60;fcntl.h&#62;
    846 #include &#60;stdio.h&#62;
    847 #include &#60;string.h&#62;
    848 #include &#60;unistd.h&#62;
    849 #include &#60;stdlib.h&#62;
    850 
    851 #include &#60;rpm/rpmlib.h&#62;</TT
    852 >
    853           </PRE
    854 ></TD
    855 ></TR
    856 ></TABLE
    857 >
    858         </P
    859 ><P
    860 >          Here we include rpmlib's definitions.
    861 
    862           <TABLE
    863 BORDER="0"
    864 BGCOLOR="#E0E0E0"
    865 WIDTH="100%"
    866 ><TR
    867 ><TD
    868 ><PRE
    869 CLASS="SCREEN"
    870 ><TT
    871 CLASS="COMPUTEROUTPUT"
    872 >void main(int argc, char ** argv)
    873 {
    874     Header h;
    875     int stat;
    876     rpmdb db;
    877     dbiIndexSet matches;</TT
    878 >
    879           </PRE
    880 ></TD
    881 ></TR
    882 ></TABLE
    883 >
    884         </P
    885 ><P
    886 >          Here are the storage declarations.
    887 
    888           <TABLE
    889 BORDER="0"
    890 BGCOLOR="#E0E0E0"
    891 WIDTH="100%"
    892 ><TR
    893 ><TD
    894 ><PRE
    895 CLASS="SCREEN"
    896 ><TT
    897 CLASS="COMPUTEROUTPUT"
    898 >    if (argc != 2) {
    899         fprintf(stderr, "showdb2 &#60;search term&#62;\n");
    900         exit(1);
    901     }
    902 
    903     rpmReadConfigFiles(NULL, NULL, NULL, 0);
    904 
    905     if (rpmdbOpen("", &#38;db, O_RDONLY, 0644) != 0) {
    906         fprintf(stderr, "cannot open /var/lib/rpm/packages.rpm\n");
    907         exit(1);
    908     }</TT
    909 >
    910           </PRE
    911 ></TD
    912 ></TR
    913 ></TABLE
    914 >
    915         </P
    916 ><P
    917 >          In this section, we do some argument processing, processing the
    918           <TT
    919 CLASS="FILENAME"
    920 >rpmrc</TT
    921 > files, and open the RPM database.
    922 
    923           <TABLE
    924 BORDER="0"
    925 BGCOLOR="#E0E0E0"
    926 WIDTH="100%"
    927 ><TR
    928 ><TD
    929 ><PRE
    930 CLASS="SCREEN"
    931 ><TT
    932 CLASS="COMPUTEROUTPUT"
    933 >    stat = rpmdbFindPackage(db, argv[1], &#38;matches);
    934     printf("Status is: %d\n", stat);
    935     if (stat == 0) {
    936       if (matches.count) {
    937         printf("Number of matches: %d\n", matches.count);
    938         h = rpmdbGetRecord(db, matches.recs[0].recOffset);
    939         if (h) headerDump(h, stdout, 1);
    940         headerFree(h);
    941         dbiFreeIndexRecord(matches);
    942       }
    943     }</TT
    944 >
    945           </PRE
    946 ></TD
    947 ></TR
    948 ></TABLE
    949 >
    950         </P
    951 ><P
    952 >          In this section we use <TT
    953 CLASS="FUNCTION"
    954 >rpmdbFindPackage()</TT
    955 > to
    956           search for the desired package.  After checking for successful status,
    957           the count of matching package records is checked.  If there is at
    958           least one match, the first matching record is retrieved, and dumped.
    959           Note that there could be more than one match.  Although this example
    960           doesn't dump more than the first matching record, it would be simple
    961           to access all matches by stepping through the
    962           <SPAN
    963 CLASS="STRUCTNAME"
    964 >matches.recs</SPAN
    965 > array.
    966         </P
    967 ><P
    968 >          Once we're done with the record, we free it, as well as the list of
    969           matching records.
    970 
    971           <TABLE
    972 BORDER="0"
    973 BGCOLOR="#E0E0E0"
    974 WIDTH="100%"
    975 ><TR
    976 ><TD
    977 ><PRE
    978 CLASS="SCREEN"
    979 ><TT
    980 CLASS="COMPUTEROUTPUT"
    981 >    rpmdbClose(db);
    982 }</TT
    983 >
    984           </PRE
    985 ></TD
    986 ></TR
    987 ></TABLE
    988 >
    989         </P
    990 ><P
    991 >          The last thing we do before exiting is to close the database.  Here's
    992           some sample output from the program.  Note the successful status, and
    993           the number of matches printed before the dump:
    994 
    995           <TABLE
    996 BORDER="0"
    997 BGCOLOR="#E0E0E0"
    998 WIDTH="100%"
    999 ><TR
   1000 ><TD
   1001 ><PRE
   1002 CLASS="SCREEN"
   1003 ><TT
   1004 CLASS="PROMPT"
   1005 ># </TT
   1006 ><TT
   1007 CLASS="USERINPUT"
   1008 ><B
   1009 >./showdb2 rpm</B
   1010 ></TT
   1011 >
   1012 <TT
   1013 CLASS="COMPUTEROUTPUT"
   1014 >Status is: 0
   1015 Number of matches: 1
   1016 Entry count: 37
   1017 Data count : 2920
   1018 
   1019              CT  TAG                  TYPE               OFSET      COUNT
   1020 Entry      : 000 (1000)NAME        STRING_TYPE        0x00000000 00000001
   1021        Data: 000 rpm
   1022 Entry      : 001 (1001)VERSION     STRING_TYPE        0x00000004 00000001
   1023        Data: 000 2.2.9
   1024 Entry      : 002 (1002)RELEASE     STRING_TYPE        0x0000000a 00000001
   1025        Data: 000 1
   1026 Entry      : 003 (1004)SUMMARY     STRING_TYPE        0x0000000c 00000001
   1027        Data: 000 Red Hat Package Manager
   1028 &#8230;
   1029 Entry      : 034 (1049)REQUIRENAME STRING_ARRAY_TYPE  0x00000b40 00000003
   1030        Data: 000 libz.so.1
   1031        Data: 001 libdb.so.2
   1032        Data: 002 libc.so.5
   1033 Entry      : 035 (1050)REQUIREVERSION STRING_ARRAY_TYPE 0x00000b5f 00000003
   1034        Data: 000 
   1035        Data: 001 
   1036        Data: 002 
   1037 Entry      : 036 (1064)RPMVERSION  STRING_TYPE        0x00000b62 00000001
   1038        Data: 000 2.2.9</TT
   1039 >
   1040 <TT
   1041 CLASS="PROMPT"
   1042 >#</TT
   1043 >
   1044           </PRE
   1045 ></TD
   1046 ></TR
   1047 ></TABLE
   1048 >
   1049         </P
   1050 ></DIV
   1051 ></DIV
   1052 ><DIV
   1053 CLASS="NAVFOOTER"
   1054 ><HR
   1055 ALIGN="LEFT"
   1056 WIDTH="100%"><TABLE
   1057 WIDTH="100%"
   1058 BORDER="0"
   1059 CELLPADDING="0"
   1060 CELLSPACING="0"
   1061 ><TR
   1062 ><TD
   1063 WIDTH="33%"
   1064 ALIGN="left"
   1065 VALIGN="top"
   1066 ><A
   1067 HREF="s1-rpm-rpmlib-functions.html"
   1068 >Prev</A
   1069 ></TD
   1070 ><TD
   1071 WIDTH="34%"
   1072 ALIGN="center"
   1073 VALIGN="top"
   1074 ><A
   1075 HREF="index.html"
   1076 >Home</A
   1077 ></TD
   1078 ><TD
   1079 WIDTH="33%"
   1080 ALIGN="right"
   1081 VALIGN="top"
   1082 ><A
   1083 HREF="p13740.html"
   1084 >Next</A
   1085 ></TD
   1086 ></TR
   1087 ><TR
   1088 ><TD
   1089 WIDTH="33%"
   1090 ALIGN="left"
   1091 VALIGN="top"
   1092 >rpmlib Functions</TD
   1093 ><TD
   1094 WIDTH="34%"
   1095 ALIGN="center"
   1096 VALIGN="top"
   1097 ><A
   1098 HREF="ch-rpm-rpmlib.html"
   1099 >Up</A
   1100 ></TD
   1101 ><TD
   1102 WIDTH="33%"
   1103 ALIGN="right"
   1104 VALIGN="top"
   1105 >Appendixes</TD
   1106 ></TR
   1107 ></TABLE
   1108 ></DIV
   1109 ></BODY
   1110 ></HTML
   1111 >