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 <errno.h> 103 #include <fcntl.h> 104 #include <stdio.h> 105 #include <unistd.h> 106 #include <string.h> 107 108 #include <rpm/rpmlib.h></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 < 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, &sig, &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… 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, &type, (void **) &name, &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, &itertag, &type, p, &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 <errno.h> 479 #include <fcntl.h> 480 #include <stdio.h> 481 #include <string.h> 482 #include <unistd.h> 483 #include <stdlib.h> 484 485 #include <rpm/rpmlib.h></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("", &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… 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, &type, (void **) &name, &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 > 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 … 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 … 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 …</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 <errno.h> 845 #include <fcntl.h> 846 #include <stdio.h> 847 #include <string.h> 848 #include <unistd.h> 849 #include <stdlib.h> 850 851 #include <rpm/rpmlib.h></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 <search term>\n"); 900 exit(1); 901 } 902 903 rpmReadConfigFiles(NULL, NULL, NULL, 0); 904 905 if (rpmdbOpen("", &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], &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 … 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 >