fix bugs in fileconflicts code and prepare for aliased dirs
[platform/upstream/libsolv.git] / tools / rpmdb2solv.c
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 <limits.h>
19 #include <fcntl.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24
25 #include "pool.h"
26 #include "repo.h"
27 #include "repo_rpmdb.h"
28 #include "repo_products.h"
29 #include "repo_solv.h"
30 #include "common_write.h"
31
32 static void
33 usage(int status)
34 {
35   fprintf(stderr, "\nUsage:\n"
36           "rpmdb2solv [-n] [-x] [-b <basefile>] [-p <productsdir>] [-r <root>]\n"
37           " -n : No packages, do not read rpmdb, useful to only parse products\n"
38           " -x : use extrapool\n"
39           " -b <basefile> : Write .solv to <basefile>.solv instead of stdout\n"
40           " -p <productsdir> : Scan <productsdir> for .prod files, representing installed products\n"
41           " -r <root> : Prefix rpmdb path and <productsdir> with <root>\n"
42           " -o <solv> : Write .solv to file instead of stdout\n"
43          );
44   exit(status);
45 }
46
47
48 int
49 main(int argc, char **argv)
50 {
51   Pool *pool = pool_create();
52   Repo *repo, *ref = 0;
53   Repodata *data;
54   int c, percent = 0;
55   int extrapool = 0;
56   int nopacks = 0;
57   const char *root = 0;
58   const char *basefile = 0;
59   const char *refname = 0;
60 #ifdef ENABLE_SUSEREPO
61   char *proddir = 0;
62 #endif
63   char *outfile = 0;
64
65   /*
66    * parse arguments
67    */
68   
69   while ((c = getopt(argc, argv, "Phnxb:r:p:o:")) >= 0)
70     switch (c)
71       {
72       case 'h':
73           usage(0);
74         break;
75       case 'r':
76         root = optarg;
77         break;
78       case 'b':
79         basefile = optarg;
80         break;
81       case 'n':
82         nopacks = 1;
83         break;
84       case 'P':
85         percent = 1;
86         break;
87       case 'p':
88 #ifdef ENABLE_SUSEREPO
89         proddir = optarg;
90 #endif
91         break;
92       case 'x':
93         extrapool = 1;
94         break;
95       case 'o':
96         outfile = optarg;
97         break;
98       default:
99         usage(1);
100       }
101   
102   if (outfile && !freopen(outfile, "w", stdout))
103     {
104       perror(outfile);
105       exit(1);
106     }
107     
108   /*
109    * optional arg is old version of rpmdb solv file
110    * should make this a real option instead
111    */
112   
113   if (optind < argc)
114     refname = argv[optind];
115
116   if (refname && !nopacks)
117     {
118       FILE *fp;
119       if ((fp = fopen(refname, "r")) == NULL)
120         {
121           perror(refname);
122         }
123       else
124         {
125           Pool *refpool = extrapool ? pool_create() : 0;
126           ref = repo_create(refpool ? refpool : pool, "ref");
127           if (repo_add_solv(ref, fp, 0) != 0)
128             {
129               fprintf(stderr, "%s: %s\n", refname, pool_errstr(ref->pool));
130               if (ref->pool != pool)
131                 pool_free(ref->pool);
132               else
133                 repo_free(ref, 1);
134               ref = 0;
135             }
136           else
137             repo_disable_paging(ref);
138           fclose(fp);
139         }
140     }
141
142   /*
143    * create 'installed' repository
144    * add products
145    * add rpmdb
146    * write .solv
147    */
148
149   if (root && *root)
150     pool_set_rootdir(pool, root);
151
152   repo = repo_create(pool, "installed");
153   data = repo_add_repodata(repo, 0);
154
155   if (!nopacks)
156     {
157       if (repo_add_rpmdb(repo, ref, REPO_USE_ROOTDIR | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE | (percent ? RPMDB_REPORT_PROGRESS : 0)))
158         {
159           fprintf(stderr, "rpmdb2solv: %s\n", pool_errstr(pool));
160           exit(1);
161         }
162     }
163
164 #ifdef ENABLE_SUSEREPO
165   if (proddir && *proddir)
166     {
167       if (root && *root)
168         {
169           int rootlen = strlen(root);
170           if (!strncmp(root, proddir, rootlen))
171             {
172               proddir += rootlen;
173               if (*proddir != '/' && proddir[-1] == '/')
174                 proddir--;
175             }
176         }
177       if (repo_add_products(repo, proddir, REPO_USE_ROOTDIR | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE))
178         {
179           fprintf(stderr, "rpmdb2solv: %s\n", pool_errstr(pool));
180           exit(1);
181         }
182     }
183 #endif
184   repodata_internalize(data);
185
186   if (ref)
187     {
188       if (ref->pool != pool)
189         pool_free(ref->pool);
190       else
191         repo_free(ref, 1);
192       ref = 0;
193     }
194
195   tool_write(repo, basefile, 0);
196   pool_free(pool);
197   exit(0);
198 }