Dump original package header into /usr/lib/sysimage/rpm-headers when
installing packages. Querying installed packages becomes trivial
with that. No separate DB needed.

PoC of a similar thing in original rpm:
https://github.com/rpm-software-management/rpm/pull/1959

Signed-off-by: Ludwig Nussel <[email protected]>
---
 archival/rpm.c | 85 ++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 72 insertions(+), 13 deletions(-)

diff --git a/archival/rpm.c b/archival/rpm.c
index af8db99a6..a53a3e7bf 100644
--- a/archival/rpm.c
+++ b/archival/rpm.c
@@ -44,6 +44,7 @@
 #define TAG_PACKAGER            1015
 #define TAG_GROUP               1016
 #define TAG_URL                 1020
+#define TAG_ARCH                1022
 #define TAG_PREIN               1023
 #define TAG_POSTIN              1024
 #define TAG_FILEFLAGS           1037
@@ -62,6 +63,8 @@
 #define RPMFILE_CONFIG          (1 << 0)
 #define RPMFILE_DOC             (1 << 1)
 
+#define HEADER_DIR "/usr/lib/sysimage/rpm-headers"
+
 enum rpm_functions_e {
        rpm_query = 1,
        rpm_install = 2,
@@ -69,7 +72,8 @@ enum rpm_functions_e {
        rpm_query_package = 8,
        rpm_query_list = 16,
        rpm_query_list_doc = 32,
-       rpm_query_list_config = 64
+       rpm_query_list_config = 64,
+       rpm_query_all = 128,
 };
 
 typedef struct {
@@ -321,17 +325,44 @@ static void extract_cpio(int fd, const char *source_rpm)
                continue;
 }
 
+static void install_header(int rpm_fd)
+{
+       int fd;
+       off_t payloadstart;
+       char* path = xasprintf("%s/%s-%s-%s.%s.rpm", HEADER_DIR,
+                                                       rpm_getstr0(TAG_NAME), 
rpm_getstr0(TAG_VERSION),
+                                                       
rpm_getstr0(TAG_RELEASE), rpm_getstr0(TAG_ARCH));
+       /* hack to avoid copy */
+       path[strlen(HEADER_DIR)] = 0;
+       bb_make_directory(path, 0755, FILEUTILS_RECUR);
+       path[strlen(HEADER_DIR)] = '/';
+
+       payloadstart = xlseek(rpm_fd, 0, SEEK_CUR);
+       xlseek(rpm_fd, 0, SEEK_SET);
+
+       fd = xopen(path, O_WRONLY|O_CREAT|O_EXCL);
+       bb_copyfd_exact_size(rpm_fd, fd, payloadstart);
+       close(fd);
+       if (payloadstart != xlseek(rpm_fd, 0, SEEK_CUR)) {
+               unlink(path);
+               bb_error_msg_and_die("failed to write header");
+       }
+}
+
 //usage:#define rpm_trivial_usage
 //usage:       "-i PACKAGE.rpm; rpm -qp[ildc] PACKAGE.rpm"
 //usage:#define rpm_full_usage "\n\n"
 //usage:       "Manipulate RPM packages\n"
 //usage:     "\nCommands:"
 //usage:     "\n       -i      Install package"
-//usage:     "\n       -qp     Query package"
-//usage:     "\n       -qpi    Show information"
-//usage:     "\n       -qpl    List contents"
-//usage:     "\n       -qpd    List documents"
-//usage:     "\n       -qpc    List config files"
+//usage:     "\n       -q      Query package"
+//usage:     "\n\nQuery Options:"
+//usage:     "\n       -p      Query package file"
+//usage:     "\n       -a      Query all installed packages"
+//usage:     "\n       -i      Show information"
+//usage:     "\n       -l      List contents"
+//usage:     "\n       -d      List documents"
+//usage:     "\n       -c      List config files"
 
 /* RPM version 4.13.0.1:
  * Unlike -q, -i seems to imply -p: -i, -ip and -pi work the same.
@@ -356,11 +387,13 @@ int rpm_main(int argc, char **argv) 
MAIN_EXTERNALLY_VISIBLE;
 int rpm_main(int argc, char **argv)
 {
        int opt, func = 0;
+       struct dirent *ent;
+       DIR* rpms = NULL;
 
        INIT_G();
        INIT_PAGESIZE(G.pagesize);
 
-       while ((opt = getopt(argc, argv, "iqpldc")) != -1) {
+       while ((opt = getopt(argc, argv, "iqpldca")) != -1) {
                switch (opt) {
                case 'i': /* First arg: Install mode, with q: Information */
                        if (!func) func = rpm_install;
@@ -384,21 +417,44 @@ int rpm_main(int argc, char **argv)
                        func |= rpm_query_list;
                        func |= rpm_query_list_config;
                        break;
+               case 'a': /* query all packages */
+                       func |= rpm_query_all;
+                       break;
                default:
                        bb_show_usage();
                }
        }
        argv += optind;
        //argc -= optind;
-       if (!argv[0]) {
+       if (!(func & rpm_query_all) && !argv[0]) {
                bb_show_usage();
        }
 
+       if (func & rpm_query && (func | rpm_query_package) != func )
+               rpms = xopendir(HEADER_DIR);
+
        for (;;) {
                int rpm_fd;
                const char *source_rpm;
 
-               rpm_fd = rpm_gettags(*argv);
+               /* query installed package */
+               if (func & rpm_query && (func | rpm_query_package) != func ) {
+                       char* path = NULL;
+                       ent = readdir(rpms);
+                       if (!ent)
+                               break;
+                       if (DOT_OR_DOTDOT(ent->d_name))
+                               continue; /* . or .. */
+                       path = concat_path_file(HEADER_DIR, ent->d_name);
+                       rpm_fd = rpm_gettags(path);
+                       free(path);
+                       if (!(func & rpm_query_all) && 
strcmp(rpm_getstr0(TAG_NAME), *argv)) {
+                               munmap(G.map, G.mapsize);
+                               free(G.mytags);
+                               continue;
+                       }
+               } else
+                       rpm_fd = rpm_gettags(*argv);
                print_all_tags();
 
                source_rpm = rpm_getstr0(TAG_SOURCERPM);
@@ -406,6 +462,7 @@ int rpm_main(int argc, char **argv)
                if (func & rpm_install) {
                        /* -i (and not -qi) */
 
+                       install_header(rpm_fd);
                        /* Backup any config files */
                        loop_through_files(TAG_BASENAMES, fileaction_dobackup);
                        /* Extact the archive */
@@ -414,8 +471,8 @@ int rpm_main(int argc, char **argv)
                        loop_through_files(TAG_BASENAMES, fileaction_setowngrp);
                }
                else
-               if ((func & (rpm_query|rpm_query_package)) == 
(rpm_query|rpm_query_package)) {
-                       /* -qp */
+               if (func & rpm_query) {
+                       /* -q */
 
                        if (!(func & (rpm_query_info|rpm_query_list))) {
                                /* If just a straight query, just give package 
name */
@@ -481,12 +538,14 @@ int rpm_main(int argc, char **argv)
                        /* Unsupported (help text shows what we support) */
                        bb_show_usage();
                }
-               if (!*++argv)
-                       break;
                munmap(G.map, G.mapsize);
                free(G.mytags);
                close(rpm_fd);
+               if (!(func & rpm_query_all) && !*++argv)
+                       break;
        }
+       if (rpms)
+               closedir(rpms);
 
        return 0;
 }
-- 
2.36.1

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to