1 /*
2 * Copyright (c) 2007, Novell Inc.
3 *
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
6 */
7
8 /*
9 * rpmdb2solv
10 *
11 * Reads rpm database (and evtl. more, like product metadata) to build
12 * a .solv file of 'installed' solvables.
13 * Writes .solv to stdout
14 *
15 */
16
17 #include <sys/types.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22
23 #ifdef ENABLE_RPMDB_LIBRPM
24 #include <rpm/rpmmacro.h>
25 #endif
26
27
28 #include "pool.h"
29 #include "repo.h"
30 #include "repo_rpmdb.h"
31 #ifdef ENABLE_PUBKEY
32 #include "repo_pubkey.h"
33 #endif
34 #include "repo_products.h"
35 #include "repo_solv.h"
36 #include "common_write.h"
37 #ifdef ENABLE_APPDATA
38 #include "repo_appdata.h"
39 #endif
40 #ifdef SUSE
41 #include "repo_autopattern.h"
42 #endif
43
44
45 static void
usage(int status)46 usage(int status)
47 {
48 fprintf(stderr, "\nUsage:\n"
49 "rpmdb2solv [-P] [-C] [-n] [-b <basefile>] [-p <productsdir>] [-r <root>]\n"
50 " -n : No packages, do not read rpmdb, useful to only parse products\n"
51 " -p <productsdir> : Scan <productsdir> for .prod files, representing installed products\n"
52 " -r <root> : Prefix rpmdb path and <productsdir> with <root>\n"
53 " -o <solv> : Write .solv to file instead of stdout\n"
54 " -P : print percentage done\n"
55 " -C : include the changelog\n"
56 );
57 exit(status);
58 }
59
60
61 int
main(int argc,char ** argv)62 main(int argc, char **argv)
63 {
64 FILE *reffp = 0;
65 Pool *pool = pool_create();
66 Repo *repo;
67 Repodata *data;
68 int c, percent = 0;
69 int nopacks = 0;
70 int add_changelog = 0;
71 const char *root = 0;
72 const char *dbpath = 0;
73 const char *refname = 0;
74 #ifdef ENABLE_SUSEREPO
75 char *proddir = 0;
76 #endif
77 char *outfile = 0;
78 #ifdef ENABLE_PUBKEY
79 int pubkeys = 0;
80 #endif
81 #ifdef ENABLE_APPDATA
82 int add_appdata = 0;
83 #endif
84 #ifdef SUSE
85 int add_auto = 0;
86 #endif
87
88 /*
89 * parse arguments
90 */
91
92 while ((c = getopt(argc, argv, "ACD:PhnkxXr:p:o:")) >= 0)
93 switch (c)
94 {
95 case 'h':
96 usage(0);
97 break;
98 case 'r':
99 root = optarg;
100 break;
101 case 'D':
102 dbpath = optarg;
103 break;
104 case 'n':
105 nopacks = 1;
106 break;
107 case 'P':
108 percent = 1;
109 break;
110 case 'p':
111 #ifdef ENABLE_SUSEREPO
112 proddir = optarg;
113 #endif
114 break;
115 case 'x':
116 break; /* extrapool no longer supported */
117 case 'X':
118 #ifdef SUSE
119 add_auto = 1;
120 #endif
121 break;
122 case 'A':
123 #ifdef ENABLE_APPDATA
124 add_appdata = 1;
125 #endif
126 break;
127 case 'o':
128 outfile = optarg;
129 break;
130 #ifdef ENABLE_PUBKEY
131 case 'k':
132 nopacks = 1;
133 pubkeys = 1;
134 break;
135 #endif
136 case 'C':
137 add_changelog = 1;
138 break;
139 default:
140 usage(1);
141 }
142
143 if (outfile && !freopen(outfile, "w", stdout))
144 {
145 perror(outfile);
146 exit(1);
147 }
148
149 /*
150 * optional arg is old version of rpmdb solv file
151 * should make this a real option instead
152 */
153
154 if (optind < argc)
155 refname = argv[optind];
156
157 if (refname && !nopacks)
158 {
159 if ((reffp = fopen(refname, "r")) == NULL)
160 perror(refname);
161 }
162
163 /*
164 * create 'installed' repository
165 * add products
166 * add rpmdb
167 * write .solv
168 */
169
170 if (root && *root)
171 pool_set_rootdir(pool, root);
172 #ifdef ENABLE_PUBKEY
173 if (dbpath && *dbpath && (!nopacks || pubkeys))
174 #else
175 if (dbpath && *dbpath && !nopacks)
176 #endif
177 {
178 #ifdef ENABLE_RPMDB_LIBRPM
179 char *macro = solv_dupjoin("_dbpath ", dbpath, 0);
180 rpmDefineMacro(NULL, macro, 0);
181 free(macro);
182 #else
183 fprintf(stderr, "cannot set dbpath without librpm\n");
184 exit(1);
185 #endif
186 }
187
188 repo = repo_create(pool, "installed");
189 data = repo_add_repodata(repo, 0);
190
191 if (!nopacks)
192 {
193 int flags = REPO_USE_ROOTDIR | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE;
194 if (percent)
195 flags |= RPMDB_REPORT_PROGRESS;
196 if (add_changelog)
197 flags |= RPM_ADD_WITH_CHANGELOG;
198 if (repo_add_rpmdb_reffp(repo, reffp, flags))
199 {
200 fprintf(stderr, "rpmdb2solv: %s\n", pool_errstr(pool));
201 exit(1);
202 }
203 }
204 #ifdef ENABLE_PUBKEY
205 if (pubkeys)
206 {
207 if (repo_add_rpmdb_pubkeys(repo, REPO_USE_ROOTDIR | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE | ADD_WITH_KEYSIGNATURES))
208 {
209 fprintf(stderr, "rpmdb2solv: %s\n", pool_errstr(pool));
210 exit(1);
211 }
212 }
213 #endif
214
215 #ifdef ENABLE_SUSEREPO
216 if (proddir && *proddir)
217 {
218 if (root && *root)
219 {
220 int rootlen = strlen(root);
221 if (!strncmp(root, proddir, rootlen))
222 {
223 proddir += rootlen;
224 if (*proddir != '/' && proddir[-1] == '/')
225 proddir--;
226 }
227 }
228 if (repo_add_products(repo, proddir, REPO_USE_ROOTDIR | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE))
229 {
230 fprintf(stderr, "rpmdb2solv: %s\n", pool_errstr(pool));
231 exit(1);
232 }
233 }
234 #endif
235
236 #ifdef ENABLE_APPDATA
237 if (add_appdata)
238 {
239 repo_add_appdata_dir(repo, "/usr/share/metainfo", REPO_USE_ROOTDIR | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE | APPDATA_SEARCH_UNINTERNALIZED_FILELIST);
240 repo_add_appdata_dir(repo, "/usr/share/appdata", REPO_USE_ROOTDIR | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE | APPDATA_SEARCH_UNINTERNALIZED_FILELIST);
241 }
242 #endif
243 repodata_internalize(data);
244
245 if (reffp)
246 fclose(reffp);
247
248 #ifdef SUSE
249 if (add_auto)
250 repo_add_autopattern(repo, ADD_NO_AUTOPRODUCTS);
251 #endif
252
253 tool_write(repo, stdout);
254 pool_free(pool);
255 exit(0);
256 }
257