[PATCH 1/2] rpm: query installed packages
Ludwig Nussel
ludwig.nussel at suse.de
Mon Jul 11 09:28:07 UTC 2022
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 <ludwig.nussel at suse.de>
---
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
More information about the busybox
mailing list