rpm/lib/ts.c

396 lines
8.0 KiB
C

#include "system.h"
#include <fnmatch.h>
#include <fts.h>
#include <rpmlib.h>
#include <rpmpgp.h>
#include "depends.h"
#include "debug.h"
static int _debug = 1;
#define BHPATH "/mnt/redhat/beehive/comps/dist"
#define BHCOLL "7.2"
#define BHN "@(basesystem|bash|filesystem|glibc-common|glibc|ldconfig|libtermcap|mktemp|setup|termcap)"
#define BHVR "*"
#define BHA "@(i[3456]86|noarch)"
const char * bhpath = BHPATH;
int bhpathlen = sizeof(BHPATH)-1;
int bhlvl = -1;
static char * const ftsSet[] = {
BHPATH, NULL,
};
struct ftsglob_s {
const char ** patterns;
int fnflags;
};
const char * lvl0[] = {
BHPATH, NULL
};
const char * lvl1[] = {
BHCOLL, NULL
};
const char * lvl2[] = {
BHN, NULL
};
const char * lvl3[] = {
BHVR, NULL
};
const char * lvl4[] = {
BHA, NULL
};
static struct ftsglob_s bhglobs[] = {
{ lvl0, (FNM_PATHNAME | FNM_PERIOD | FNM_EXTMATCH) },
{ lvl1, (FNM_PATHNAME | FNM_PERIOD | FNM_EXTMATCH) },
{ lvl2, (FNM_PATHNAME | FNM_PERIOD | FNM_EXTMATCH) },
{ lvl3, (FNM_PATHNAME | FNM_PERIOD | FNM_EXTMATCH) },
{ lvl4, (FNM_PATHNAME | FNM_PERIOD | FNM_EXTMATCH) },
};
static int nbhglobs = sizeof(bhglobs)/sizeof(bhglobs[0]);
static const char * ftsInfoStrings[] = {
"UNKNOWN",
"D",
"DC",
"DEFAULT",
"DNR",
"DOT",
"DP",
"ERR",
"F",
"INIT",
"NS",
"NSOK",
"SL",
"SLNONE",
"W",
};
static const char * ftsInfoStr(int fts_info) {
if (!(fts_info >= 1 && fts_info <= 14))
fts_info = 0;
return ftsInfoStrings[ fts_info ];
}
static int ftsPrint(FTS * ftsp, FTSENT * fts, rpmTransactionSet ts)
{
struct ftsglob_s * bhg;
const char ** patterns;
const char * pattern;
const char * n, * v, * r;
const char * s;
FD_t fd = NULL;
Header h = NULL;
rpmRC rc;
int indent = 2;
int lvl;
int xx;
switch (fts->fts_info) {
case FTS_D: /* preorder directory */
if (fts->fts_pathlen < bhpathlen)
break;
/* Grab the level of the beehive top directory. */
if (bhlvl < 0) {
if (fts->fts_pathlen == bhpathlen && !strcmp(fts->fts_path, bhpath))
bhlvl = fts->fts_level;
else
break;
}
lvl = fts->fts_level - bhlvl;
if (lvl < 0)
break;
#if 0
fprintf(stderr, "FTS_%s\t%*s %s\n", ftsInfoStr(fts->fts_info),
indent * (fts->fts_level < 0 ? 0 : fts->fts_level), "",
fts->fts_name);
#endif
/* Full path glob expression check. */
bhg = bhglobs;
if ((patterns = bhg->patterns) != NULL)
while ((pattern = *patterns++) != NULL) {
if (*pattern == '/')
xx = fnmatch(pattern, fts->fts_path, bhg->fnflags);
else
xx = fnmatch(pattern, fts->fts_name, bhg->fnflags);
if (xx == 0)
break;
}
/* Level specific glob expression check(s). */
if (lvl == 0 || lvl >= nbhglobs)
break;
bhg += lvl;
if ((patterns = bhg->patterns) != NULL)
while ((pattern = *patterns++) != NULL) {
if (*pattern == '/')
xx = fnmatch(pattern, fts->fts_path, bhg->fnflags);
else
xx = fnmatch(pattern, fts->fts_name, bhg->fnflags);
if (xx == 0)
break;
else
xx = fts_set(ftsp, fts, FTS_SKIP);
}
break;
case FTS_DP: /* postorder directory */
#if 0
fprintf(stderr, "FTS_%s\t%*s %s\n", ftsInfoStr(fts->fts_info),
indent * (fts->fts_level < 0 ? 0 : fts->fts_level), "",
fts->fts_name);
#endif
break;
case FTS_F: /* regular file */
if (fts->fts_level >= 0) {
if (strcmp(fts->fts_parent->fts_name, "SRPMS")) {
xx = fts_set(ftsp, fts->fts_parent, FTS_SKIP);
break;
}
}
s = fts->fts_name + fts->fts_namelen + 1 - sizeof(".rpm");
if (strcmp(s, ".rpm"))
break;
rpmMessage(RPMMESS_DEBUG, "============== %s\n", fts->fts_accpath);
fd = Fopen(fts->fts_accpath, "r");
if (fd == NULL || Ferror(fd))
break;
rc = rpmReadPackageFile(ts, fd, fts->fts_path, &h);
xx = Fclose(fd);
fd = NULL;
if (rc != RPMRC_OK)
break;
xx = headerNVR(h, &n, &v, &r);
fprintf(stderr, "\t%*s %s-%s-%s\n",
indent * (fts->fts_level < 0 ? 0 : fts->fts_level), "",
n, v, r);
#ifdef NOTYET
xx = rpmtransAddPackage(ts, h, fts->fts_path, 1, NULL);
#endif
break;
case FTS_NS: /* stat(2) failed */
case FTS_DNR: /* unreadable directory */
case FTS_ERR: /* error; errno is set */
fprintf(stderr, "FTS_%s\t%*s %s\n", ftsInfoStr(fts->fts_info),
indent * (fts->fts_level < 0 ? 0 : fts->fts_level), "",
fts->fts_name);
break;
case FTS_DC: /* directory that causes cycles */
case FTS_DEFAULT: /* none of the above */
case FTS_DOT: /* dot or dot-dot */
case FTS_INIT: /* initialized only */
case FTS_NSOK: /* no stat(2) requested */
case FTS_SL: /* symbolic link */
case FTS_SLNONE: /* symbolic link without target */
case FTS_W: /* whiteout object */
default:
fprintf(stderr, "FTS_%s\t%*s %s\n", ftsInfoStr(fts->fts_info),
indent * (fts->fts_level < 0 ? 0 : fts->fts_level), "",
fts->fts_name);
break;
}
h = headerFree(h, "ftsPrint exit");
if (fd)
xx = Fclose(fd);
return 0;
}
static int depth;
static int level;
static int globx;
static void go (const char * sb, const char * se)
{
const char * s = sb;
int blvl = 0;
int plvl = 0;
int c;
globx = -1;
while ( s < se && (c = *s) != '\0' ) {
s++;
switch (c) {
case '+':
case '@':
case '!':
continue;
case '?':
case '*':
if (*s == '(')
continue;
if (globx < 0)
globx = (s - sb - 1);
continue;
case '[':
blvl++;
continue;
case ']':
if (!blvl)
continue;
--blvl;
if (!blvl && globx < 0)
globx = (s - sb - 1);
continue;
case '(':
plvl++;
continue;
case '|':
continue;
case ')':
if (!plvl)
continue;
--plvl;
if (!plvl && globx < 0)
globx = (s - sb - 1);
continue;
case '\\':
if (*s)
s++;
continue;
case '/':
depth++;
continue;
default:
continue;
}
}
}
static struct poptOption optionsTable[] = {
{ "verbose", 'v', 0, 0, 'v', NULL, NULL },
{ "debug", 'd', POPT_ARG_VAL, &_debug, -1, NULL, NULL },
POPT_AUTOHELP
POPT_TABLEEND
};
int
main(int argc, const char *argv[])
{
poptContext optCon = poptGetContext(argv[0], argc, argv, optionsTable, 0);
const char * rootDir = "";
rpmdb db = NULL;
rpmTransactionSet ts = NULL;
FTS * ftsp;
int ftsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT);
FTSENT * fts;
char buf[BUFSIZ];
const char ** args;
const char * arg;
char * t;
int rc;
int ec = 1;
int xx;
while ((rc = poptGetNextOpt(optCon)) > 0) {
switch (rc) {
case 'v':
rpmIncreaseVerbosity();
/*@switchbreak@*/ break;
default:
/*@switchbreak@*/ break;
}
}
rpmReadConfigFiles(NULL, NULL);
if (_debug) {
rpmIncreaseVerbosity();
rpmIncreaseVerbosity();
}
ts = rpmtransCreateSet(db, rootDir);
(void) rpmtsOpenDB(ts, O_RDONLY);
args = poptGetArgs(optCon);
t = buf;
*t = '\0';
t = stpcpy(t, BHPATH);
*t++ = '/';
t = stpcpy(t, BHCOLL);
*t++ = '/';
if (args == NULL)
t = stpcpy(t, BHN);
else {
t = stpcpy(t, "@(");
while ((arg = *args++) != NULL) {
t = stpcpy(t, arg);
*t++ = '|';
}
t[-1] = ')';
}
*t++ = '/';
t = stpcpy(t, BHVR);
*t++ = '/';
t = stpcpy(t, BHA);
fprintf(stderr, "*** \"%s\"\n", buf);
level = 0;
depth = (buf[0] == '/') ? -1 : 0;
globx = -1;
go(buf, buf+strlen(buf));
fprintf(stderr, "*** \"%s/%s/%s/%s/%s\"\n", *lvl0, *lvl1, *lvl2, *lvl3, *lvl4);
#if 0
lvl0[0] = buf;
#endif
if (!_debug) {
ftsp = fts_open(ftsSet, ftsOpts, NULL);
while((fts = fts_read(ftsp)) != NULL)
xx = ftsPrint(ftsp, fts, ts);
xx = fts_close(ftsp);
}
#ifdef NOTYET
if (!_debug) {
{ rpmProblem conflicts = NULL;
int numConflicts = 0;
(void) rpmdepCheck(ts, &conflicts, &numConflicts);
/*@-branchstate@*/
if (conflicts) {
rpmMessage(RPMMESS_ERROR, _("failed dependencies:\n"));
printDepProblems(stderr, conflicts, numConflicts);
conflicts = rpmdepFreeConflicts(conflicts, numConflicts);
}
/*@=branchstate@*/
}
(void) rpmdepOrder(ts);
}
#endif
exit:
ts = rpmtransFree(ts);
return ec;
}