Add --qf to rpmgi.
[tools/librpm-tizen.git] / lib / rpmgi.c
1 /*@-modfilesys@*/
2 /** \ingroup rpmio
3  * \file rpmio/rpmio.c
4  */
5 #include "system.h"
6
7 #define _RPMGI_INTERNAL
8 #include <rpmgi.h>
9
10 #include <rpmdb.h>
11
12 #include "debug.h"
13
14 /*@unchecked@*/
15 int _rpmgi_debug = 0;
16
17 rpmgi XrpmgiUnlink(rpmgi gi, const char * msg, const char * fn, unsigned ln)
18 {
19     if (gi == NULL) return NULL;
20
21 if (_rpmgi_debug && msg != NULL)
22 fprintf(stderr, "--> gi %p -- %d %s at %s:%u\n", gi, gi->nrefs, msg, fn, ln);
23
24     gi->nrefs--;
25     return NULL;
26 }
27
28 rpmgi XrpmgiLink(rpmgi gi, const char * msg, const char * fn, unsigned ln)
29 {
30     if (gi == NULL) return NULL;
31     gi->nrefs++;
32
33 if (_rpmgi_debug && msg != NULL)
34 fprintf(stderr, "--> gi %p ++ %d %s at %s:%u\n", gi, gi->nrefs, msg, fn, ln);
35
36     /*@-refcounttrans@*/ return gi; /*@=refcounttrans@*/
37 }
38
39 rpmgi rpmgiFree(rpmgi gi)
40 {
41     if (gi == NULL)
42         return NULL;
43
44     if (gi->nrefs > 1)
45         return rpmgiUnlink(gi, NULL);
46
47 if (_rpmgi_debug < 0)
48 fprintf(stderr, "*** gi %p\t%p[%d]\n", gi, gi->argv, gi->argc);
49
50     (void) rpmgiUnlink(gi, NULL);
51
52     switch (gi->tag) {
53     default:
54     case RPMGI_RPMDB:
55         break;
56     case RPMGI_HDLIST:
57         break;
58     case RPMGI_ARGLIST:
59         break;
60     case RPMGI_FTSWALK:
61         break;
62     }
63
64     gi->queryFormat = _free(gi->queryFormat);
65     if (gi->ftsp != NULL) {
66         int xx;
67         xx = Fts_close(gi->ftsp);
68         gi->ftsp = NULL;
69         gi->fts = NULL;
70     }
71     gi->mi = rpmdbFreeIterator(gi->mi);
72     gi->ts = rpmtsFree(gi->ts);
73
74     memset(gi, 0, sizeof(*gi));         /* XXX trash and burn */
75     gi = _free(gi);
76     return NULL;
77 }
78
79 rpmgi rpmgiNew(rpmts ts, int tag, const void * keyp, size_t keylen)
80 {
81     rpmgi gi = xcalloc(1, sizeof(*gi));
82
83     if (gi == NULL)
84         return NULL;
85
86     gi->ts = rpmtsLink(ts, NULL);
87     gi->tag = tag;
88     gi->i = -1;
89
90     switch (gi->tag) {
91     default:
92     case RPMGI_RPMDB:
93         gi->mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, NULL, 0);
94
95 if (_rpmgi_debug < 0)
96 fprintf(stderr, "*** gi %p\t%p\n", gi, gi->mi);
97
98         break;
99     case RPMGI_HDLIST:
100         break;
101     case RPMGI_ARGLIST:
102     case RPMGI_FTSWALK:
103     {   char *const * argv = keyp;
104         unsigned flags = keylen;
105
106         gi->argv = argv;
107         gi->argc = 0;
108         if (argv != NULL)
109         while (*argv++ != NULL)
110            gi->argc++;
111         gi->ftsOpts = flags;
112
113 if (_rpmgi_debug < 0)
114 fprintf(stderr, "*** gi %p\t%p[%d]\n", gi, gi->argv, gi->argc);
115
116     }   break;
117     }
118
119     gi = rpmgiLink(gi, NULL);
120
121     return gi;
122 }
123
124 static int indent = 2;
125
126 static const char * ftsInfoStrings[] = {
127     "UNKNOWN",
128     "D",
129     "DC",
130     "DEFAULT",
131     "DNR",
132     "DOT",
133     "DP",
134     "ERR",
135     "F",
136     "INIT",
137     "NS",
138     "NSOK",
139     "SL",
140     "SLNONE",
141     "W",
142 };
143
144 static const char * ftsInfoStr(int fts_info) {
145     if (!(fts_info >= 1 && fts_info <= 14))
146         fts_info = 0;
147     return ftsInfoStrings[ fts_info ];
148 }
149
150 /*@only@*/
151 static const char * rpmgiPathOrQF(rpmgi gi, const char * fn,
152                 /*@null@*/ Header * hdrp)
153         /*@modifies gi, *hdrp @*/
154 {
155     const char * fmt = ((gi->queryFormat != NULL)
156         ? gi->queryFormat : "%{name}-%{version}-%{release}");
157     const char * val = NULL;
158     Header h = NULL;
159
160     if (hdrp != NULL && *hdrp != NULL)
161         h = headerLink(*hdrp);
162
163     if (h != NULL)
164         val = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, NULL);
165     else
166         val = xstrdup(fn);
167
168     h = headerFree(h);
169
170     return val;
171 }
172
173 const char * rpmgiNext(/*@null@*/ rpmgi gi)
174         /*@modifies gi @*/
175 {
176     const char * val = NULL;
177     Header h = NULL;
178
179     if (gi != NULL && ++gi->i >= 0)
180     switch (gi->tag) {
181     default:
182     case RPMGI_RPMDB:
183         h = rpmdbNextIterator(gi->mi);
184         if (h != NULL) {
185             val = rpmgiPathOrQF(gi, "rpmdb", &h);
186         } else {
187             gi->mi = rpmdbFreeIterator(gi->mi);
188             gi->i = -1;
189         }
190         break;
191     case RPMGI_HDLIST:
192         break;
193     case RPMGI_ARGLIST:
194         if (gi->argv != NULL && gi->argv[gi->i] != NULL) {
195 if (_rpmgi_debug  < 0)
196 fprintf(stderr, "*** gi %p\t%p[%d]: %s\n", gi, gi->argv, gi->i, gi->argv[gi->i]);
197             val = rpmgiPathOrQF(gi, gi->argv[gi->i], NULL);
198         } else
199             gi->i = -1;
200         break;
201     case RPMGI_FTSWALK:
202         if (gi->argv == NULL)
203             break;
204         if (gi->ftsp == NULL && gi->i == 0) {
205             gi->ftsp = Fts_open(gi->argv, gi->ftsOpts, NULL);
206             /* XXX NULL with open(2)/malloc(3) errno set */
207         }
208
209         if (gi->ftsp != NULL)
210         while (val == NULL && (gi->fts = Fts_read(gi->ftsp)) != NULL) {
211             FTSENT * fts = gi->fts;
212
213 if (_rpmgi_debug < 0)
214 fprintf(stderr, "FTS_%s\t%*s %s\n", ftsInfoStr(fts->fts_info),
215                 indent * (fts->fts_level < 0 ? 0 : fts->fts_level), "",
216                 fts->fts_name);
217
218             switch (fts->fts_info) {
219             case FTS_F:
220             case FTS_SL:
221 if (_rpmgi_debug  < 0)
222 fprintf(stderr, "*** gi %p\t%p[%d]: %s\n", gi, gi->ftsp, gi->i, fts->fts_path);
223                 val = rpmgiPathOrQF(gi, fts->fts_path, NULL);
224                 break;
225             default:
226                 break;
227             }
228         }
229         if (gi->fts == NULL && gi->ftsp != NULL) {
230             int xx;
231             xx = Fts_close(gi->ftsp);
232             gi->ftsp = NULL;
233             gi->i = -1;
234         }
235         break;
236     }
237
238     return val;
239 }
240
241 int rpmgiSetQueryFormat(rpmgi gi, const char * queryFormat)
242 {
243     int rc = 0;
244                                                                                 
245     if (gi != NULL) {
246         gi->queryFormat = _free(gi->queryFormat);
247         gi->queryFormat = xstrdup(queryFormat);
248     }
249     return rc;
250
251 }
252
253 /*@=modfilesys@*/