7 #define _RPMGI_INTERNAL
11 #include <rpmmacro.h> /* XXX rpmExpand */
16 /*@access rpmdbMatchIterator @*/
22 static int indent = 2;
24 /*@unchecked@*/ /*@observer@*/
25 static const char * ftsInfoStrings[] = {
44 static const char * ftsInfoStr(int fts_info)
48 if (!(fts_info >= 1 && fts_info <= 14))
51 return ftsInfoStrings[ fts_info ];
56 * Open a file after macro expanding path.
57 * @param path file path
58 * @param fmode open mode
62 static FD_t rpmgiOpen(const char * path, const char * fmode)
63 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
64 /*@modifies rpmGlobalMacroContext, h_errno, internalState @*/
66 const char * fn = rpmExpand(path, NULL);
67 FD_t fd = Fopen(fn, fmode);
69 if (fd == NULL || Ferror(fd)) {
70 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), fn, Fstrerror(fd));
71 if (fd != NULL) (void) Fclose(fd);
80 * Load manifest into iterator arg list.
81 * @param gi generalized iterator
82 * @param path file path
83 * @return RPMRC_OK on success
85 static rpmRC rpmgiLoadManifest(rpmgi gi, const char * path)
86 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
87 /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/
89 FD_t fd = rpmgiOpen(path, "r.ufdio");
90 rpmRC rpmrc = RPMRC_FAIL;
93 rpmrc = rpmReadPackageManifest(fd, &gi->argc, &gi->argv);
100 * Return header from package.
101 * @param gi generalized iterator
102 * @param path file path
103 * @return header (NULL on failure)
106 static Header rpmgiReadHeader(rpmgi gi, const char * path)
107 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
108 /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/
110 FD_t fd = rpmgiOpen(path, "r.ufdio");
114 /* XXX what if path needs expansion? */
115 rpmRC rpmrc = rpmReadPackageFile(gi->ts, fd, path, &h);
121 /* XXX Read a package manifest. Restart ftswalk on success. */
126 case RPMRC_NOTTRUSTED:
137 * Read next header from package, lazily expanding manifests as found.
138 * @param gi generalized iterator
139 * @return RPMRC_OK on success
142 static rpmRC rpmgiLoadReadHeader(rpmgi gi)
143 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
144 /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/
146 rpmRC rpmrc = RPMRC_NOTFOUND;
150 const char * fn; /* XXX gi->hdrPath? */
152 fn = gi->argv[gi->i];
153 h = rpmgiReadHeader(gi, fn);
159 /* Not a header, so try for a manifest. */
160 gi->argv[gi->i] = NULL; /* HACK */
161 rpmrc = rpmgiLoadManifest(gi, fn);
162 if (rpmrc != RPMRC_OK) {
163 gi->argv[gi->i] = fn; /* HACK */
169 if (rpmrc == RPMRC_OK && h != NULL)
170 gi->h = headerLink(h);
177 * Read next header from package, lazily walking file tree.
178 * @param gi generalized iterator
179 * @return RPMRC_OK on success
182 static rpmRC rpmgiWalkReadHeader(rpmgi gi)
183 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
184 /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/
186 rpmRC rpmrc = RPMRC_NOTFOUND;
189 if (gi->ftsp != NULL)
190 while ((gi->fts = Fts_read(gi->ftsp)) != NULL) {
191 FTSENT * fts = gi->fts;
193 if (_rpmgi_debug < 0)
194 fprintf(stderr, "FTS_%s\t%*s %s\n", ftsInfoStr(fts->fts_info),
195 indent * (fts->fts_level < 0 ? 0 : fts->fts_level), "",
199 switch (fts->fts_info) {
202 if (_rpmgi_debug < 0)
203 fprintf(stderr, "*** gi %p\t%p[%d]: %s\n", gi, gi->ftsp, gi->i, fts->fts_path);
204 h = rpmgiReadHeader(gi, fts->fts_path);
205 /*@switchbreak@*/ break;
207 /*@switchbreak@*/ break;
216 if (rpmrc == RPMRC_OK && h != NULL)
217 gi->h = headerLink(h);
224 * Append globbed arg list to iterator.
225 * @param gi generalized iterator
226 * @param argv arg list to be globbed
227 * @returns RPMRC_OK on success
229 static rpmRC rpmgiGlobArgv(rpmgi gi, ARGV_t argv)
230 /*@globals internalState @*/
231 /*@modifies gi, internalState @*/
234 rpmRC rpmrc = RPMRC_OK;
237 while ((arg = *argv++) != NULL) {
242 xx = rpmGlob(arg, &ac, &av);
243 xx = argvAppend(&gi->argv, av);
251 rpmgi XrpmgiUnlink(rpmgi gi, const char * msg, const char * fn, unsigned ln)
253 if (gi == NULL) return NULL;
255 if (_rpmgi_debug && msg != NULL)
256 fprintf(stderr, "--> gi %p -- %d %s at %s:%u\n", gi, gi->nrefs, msg, fn, ln);
262 rpmgi XrpmgiLink(rpmgi gi, const char * msg, const char * fn, unsigned ln)
264 if (gi == NULL) return NULL;
267 if (_rpmgi_debug && msg != NULL)
268 fprintf(stderr, "--> gi %p ++ %d %s at %s:%u\n", gi, gi->nrefs, msg, fn, ln);
270 /*@-refcounttrans@*/ return gi; /*@=refcounttrans@*/
273 rpmgi rpmgiFree(rpmgi gi)
279 return rpmgiUnlink(gi, NULL);
281 if (_rpmgi_debug < 0)
282 fprintf(stderr, "*** gi %p\t%p[%d]\n", gi, gi->argv, gi->argc);
284 (void) rpmgiUnlink(gi, NULL);
288 gi->hdrPath = _free(gi->hdrPath);
289 gi->h = headerFree(gi->h);
291 gi->argv = argvFree(gi->argv);
293 if (gi->ftsp != NULL) {
295 xx = Fts_close(gi->ftsp);
299 if (gi->fd != NULL) {
300 (void) Fclose(gi->fd);
303 gi->mi = rpmdbFreeIterator(gi->mi);
304 gi->ts = rpmtsFree(gi->ts);
306 memset(gi, 0, sizeof(*gi)); /* XXX trash and burn */
314 rpmgi rpmgiNew(rpmts ts, int tag, const void * keyp, size_t keylen)
316 rpmgi gi = xcalloc(1, sizeof(*gi));
321 gi->ts = rpmtsLink(ts, NULL);
334 gi->argv = xcalloc(1, sizeof(*gi->argv));
340 gi = rpmgiLink(gi, NULL);
345 rpmRC rpmgiNext(/*@null@*/ rpmgi gi)
348 rpmRC rpmrc = RPMRC_NOTFOUND;
354 /* Free header from previous iteration. */
355 gi->h = headerFree(gi->h);
356 gi->hdrPath = _free(gi->hdrPath);
363 case RPMDBI_PACKAGES:
365 gi->mi = rpmtsInitIterator(gi->ts, gi->tag, gi->keyp, gi->keylen);
366 if (_rpmgi_debug < 0)
367 fprintf(stderr, "*** gi %p\t%p\n", gi, gi->mi);
370 if (gi->mi != NULL) { /* XXX unnecessary */
371 Header h = rpmdbNextIterator(gi->mi);
373 gi->h = headerLink(h);
374 sprintf(hnum, "%u", rpmdbGetIteratorOffset(gi->mi));
378 gi->mi = rpmdbFreeIterator(gi->mi);
381 gi->hdrPath = rpmExpand("rpmdb h# ", hnum, NULL);
385 const char * path = "/usr/share/comps/%{_arch}/hdlist";
386 gi->fd = rpmgiOpen(path, "r.ufdio");
389 if (gi->fd != NULL) {
390 gi->h = headerRead(gi->fd, HEADER_MAGIC_YES);
391 sprintf(hnum, "%u", (unsigned)gi->i);
395 if (gi->fd != NULL) (void) Fclose(gi->fd);
399 gi->hdrPath = rpmExpand("hdlist h# ", hnum, NULL);
402 if (gi->argv == NULL || gi->argv[gi->i] == NULL)
405 if (_rpmgi_debug < 0)
406 fprintf(stderr, "*** gi %p\t%p[%d]: %s\n", gi, gi->argv, gi->i, gi->argv[gi->i]);
407 /* Read next header, lazily expanding manifests as found. */
408 rpmrc = rpmgiLoadReadHeader(gi);
410 if (rpmrc != RPMRC_OK) /* XXX check this */
413 gi->hdrPath = xstrdup(gi->argv[gi->i]);
416 if (gi->argv == NULL) /* HACK */
420 gi->ftsp = Fts_open((char *const *)gi->argv, gi->ftsOpts, NULL);
421 /* XXX NULL with open(2)/malloc(3) errno set */
425 /* Read next header, lazily walking file tree. */
426 rpmrc = rpmgiWalkReadHeader(gi);
428 if (gi->h == NULL || rpmrc != RPMRC_OK) {
429 xx = Fts_close(gi->ftsp);
435 gi->hdrPath = xstrdup(gi->fts->fts_path);
440 if (gi->flags & 0x1) {
441 xx = rpmtsAddInstallElement(gi->ts, gi->h, (fnpyKey)gi->hdrPath, 0, NULL);
442 /* TODO save header and path in rpmte. */
448 if (gi->flags & 0x2) {
449 xx = rpmtsCheck(gi->ts);
450 xx = rpmtsOrder(gi->ts);
452 gi->h = headerFree(gi->h);
453 gi->hdrPath = _free(gi->hdrPath);
459 const char * rpmgiHdrPath(rpmgi gi)
461 return (gi != NULL ? gi->hdrPath : NULL);
464 Header rpmgiHeader(rpmgi gi)
466 /*@-compdef -refcounttrans -retexpose -usereleased@*/
467 return (gi != NULL ? gi->h : NULL);
468 /*@=compdef =refcounttrans =retexpose =usereleased@*/
471 rpmts rpmgiTs(rpmgi gi)
473 /*@-compdef -refcounttrans -retexpose -usereleased@*/
474 return (gi != NULL ? gi->ts : NULL);
475 /*@=compdef =refcounttrans =retexpose =usereleased@*/
478 rpmRC rpmgiSetArgs(rpmgi gi, ARGV_t argv, int ftsOpts, int flags)
480 rpmRC rpmrc = rpmgiGlobArgv(gi, argv);
481 gi->ftsOpts = ftsOpts;