document '-o'
[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           " -a <attr> : Only print this attribute, no .solv generation. E.g. '-a distribution.target'\n"
38           " -n : No packages, do not read rpmdb, useful to only parse products\n"
39           " -x : use extrapool\n"
40           " -b <basefile> : Write .solv to <basefile>.solv instead of stdout\n"
41           " -p <productsdir> : Scan <productsdir> for .prod files, representing installed products\n"
42           " -r <root> : Prefix rpmdb path and <productsdir> with <root>\n"
43           " -o <solv> : Write .solv to file instead of stdout\n"
44          );
45   exit(status);
46 }
47
48
49 int
50 main(int argc, char **argv)
51 {
52   Pool *pool = pool_create();
53   Repo *repo, *ref = 0;
54   Repodata *data;
55   FILE *fp;
56   Pool *refpool;
57   int c, percent = 0;
58   int extrapool = 0;
59   int nopacks = 0;
60   const char *root = 0;
61   const char *basefile = 0;
62   char *proddir = 0;
63   const char *attribute = 0;
64   char *outfile = 0;
65
66   /*
67    * parse arguments
68    */
69   
70   while ((c = getopt(argc, argv, "Pa:hnxb:r:p:o:")) >= 0)
71     switch (c)
72       {
73       case 'h':
74           usage(0);
75         break;
76       case 'a':
77         attribute = optarg;
78         break;
79       case 'r':
80         root = optarg;
81         break;
82       case 'b':
83         basefile = optarg;
84         break;
85       case 'n':
86         nopacks = 1;
87         break;
88       case 'P':
89         percent = 1;
90         break;
91       case 'p':
92         proddir = optarg;
93         break;
94       case 'x':
95         extrapool = 1;
96         break;
97       case 'o':
98         outfile = optarg;
99         break;
100       default:
101         usage(1);
102       }
103   
104   if (outfile && !freopen(outfile, "w", stdout))
105     {
106       perror(outfile);
107       exit(1);
108     }
109     
110   /*
111    * ???
112    */
113   
114   if (optind < argc)
115     {
116       if (extrapool)
117         refpool = pool_create();
118       else
119         refpool = pool;
120       if ((fp = fopen(argv[optind], "r")) == NULL)
121         {
122           perror(argv[optind]);
123           exit(1);
124         }
125       ref = repo_create(refpool, "ref");
126       repo_add_solv(ref, fp);
127       repo_disable_paging(ref);
128       fclose(fp);
129     }
130
131   /*
132    * create 'installed' repository
133    * add products
134    * add rpmdb
135    * write .solv
136    */
137
138   repo = repo_create(pool, "installed");
139   data = repo_add_repodata(repo, 0);
140
141   if (!nopacks)
142     repo_add_rpmdb(repo, ref, root, REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE | (percent ? RPMDB_REPORT_PROGRESS : 0));
143
144   if (proddir && *proddir)
145     {
146       char *buf = proddir;
147       /* if <root> given, not '/', and proddir does not start with <root> */
148       if (root && *root)
149         {
150           int rootlen = strlen(root);
151           if (strncmp(root, proddir, rootlen))
152             {
153               buf = (char *)sat_malloc(rootlen + strlen(proddir) + 2); /* + '/' + \0 */
154               strcpy(buf, root);
155               if (root[rootlen - 1] != '/' && *proddir != '/')
156                 buf[rootlen++] = '/';
157               strcpy(buf + rootlen, proddir);
158             }
159         }
160       repo_add_products(repo, proddir, root, attribute, REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE);
161       if (buf != proddir)
162         sat_free(buf);
163     }
164       
165   repodata_internalize(data);
166
167   if (ref)
168     {
169       if (ref->pool != pool)
170         pool_free(ref->pool);
171       else
172         repo_free(ref, 1);
173       ref = 0;
174     }
175
176   if (!attribute)
177     tool_write(repo, basefile, 0);
178
179   pool_free(pool);
180
181   exit(0);
182 }