rpm-build/build/checkFiles.c
Alexey Tourbin 856fad26a6 build/checkFiles.c: disable intersection check for /usr/src/debug
Though the intersection check can be useful even for /usr/src/debug
(it indicates binary code duplication and/or poor dependencies between
subpackages), it is too noisy and can eat up quite a bit of output.
The same information is still available directly within the packages
or via contents_index.
2011-02-05 23:54:19 +03:00

203 lines
4.6 KiB
C

/*
* checkFiles.c - check packaged file list.
* Written by Alexey Tourbin <at@altlinux.org>.
* License: GPLv2+.
*/
#include "system.h"
#include "rpmio_internal.h"
#include "rpmbuild.h"
#include "psm.h"
#include "checkFiles.h"
void fiIntersect(TFI_t fi1, TFI_t fi2, void (*cb)(char *f, int i1, int i2))
{
if (fi1 == NULL) return;
if (fi2 == NULL) return;
int i1 = 0, i2 = 0;
while (i1 < fi1->fc && i2 < fi2->fc) {
char f1[PATH_MAX], f2[PATH_MAX];
strcpy(f1, fi1->dnl[fi1->dil[i1]] + fi1->astriplen);
strcpy(f2, fi2->dnl[fi2->dil[i2]] + fi2->astriplen);
strcat(f1, fi1->bnl[i1]);
strcat(f2, fi2->bnl[i2]);
int cmp = strcmp(f1, f2);
if (cmp < 0) {
i1++;
continue;
}
if (cmp > 0) {
i2++;
continue;
}
cb(f1, i1, i2);
i1++;
i2++;
}
}
static
void checkPkgIntersect(Package pkg1, Package pkg2)
{
TFI_t fi1 = pkg1->cpioList;
TFI_t fi2 = pkg2->cpioList;
if (fi1 == NULL) return;
if (fi2 == NULL) return;
int once = 0;
void cb(char *f, int i1, int i2)
{
if (S_ISDIR(fi1->fmodes[i1]) && S_ISDIR(fi2->fmodes[i2]))
return;
const char src[] = "/usr/src/debug/";
if (strncmp(f, src, sizeof(src) - 1) == 0)
return;
if (once++ == 0)
rpmlog(RPMLOG_WARNING,
"File(s) packaged into both %s-%s-%s and %s-%s-%s:\n",
fi1->name, fi1->version, fi1->release,
fi2->name, fi2->version, fi2->release);
rpmlog(RPMLOG_INFO, " %s\n", f);
}
fiIntersect(fi1, fi2, cb);
}
static
void checkIntersect(Spec spec)
{
Package pkg1, pkg2;
for (pkg1 = spec->packages; pkg1; pkg1 = pkg1->next)
for (pkg2 = pkg1->next; pkg2; pkg2 = pkg2->next)
checkPkgIntersect(pkg1, pkg2);
}
static
int fiSearch(TFI_t fi, const char *path)
{
if (fi == NULL || fi->fc == 0)
return -1;
int l = 0;
int u = fi->fc;
while (l < u) {
int i = (l + u) / 2;
const char *d = fi->dnl[fi->dil[i]];
int dlen = strlen(d);
int cmp = strncmp(path, d, dlen);
if (cmp == 0) {
const char *b = fi->bnl[i];
cmp = strcmp(path + dlen, b);
}
if (cmp < 0)
u = i;
else if (cmp > 0)
l = i + 1;
else
return i;
}
return -1;
}
#include <fts.h>
static
int checkUnpackaged(Spec spec)
{
int rc = 0;
int uc = 0;
char **uv = NULL;
int avcmp(const void *sptr1, const void *sptr2)
{
const char *s1 = *(const char **) sptr1;
const char *s2 = *(const char **) sptr2;
return strcmp(s1, s2);
}
if (spec->exclude)
qsort(spec->exclude, spec->excludeCount, sizeof(char *), avcmp);
void check(const char *path)
{
Package pkg;
for (pkg = spec->packages; pkg; pkg = pkg->next)
if (fiSearch(pkg->cpioList, path) >= 0)
return;
if (spec->exclude) {
const char *key = path + strlen(spec->buildRootURL);
if (bsearch(&key, spec->exclude, spec->excludeCount,
sizeof(char *), avcmp))
return;
}
AUTO_REALLOC(uv, uc, 8);
uv[uc++] = xstrdup(path + strlen(spec->buildRootURL));
rc |= 1;
}
char *paths[] = { (char *) spec->buildRootURL, 0 };
int options = FTS_COMFOLLOW | FTS_PHYSICAL;
FTS *ftsp = fts_open(paths, options, NULL);
FTSENT *fts;
while ((fts = fts_read(ftsp)) != NULL) {
// buildroot may not exist
if (fts->fts_level == 0 && fts->fts_info == FTS_NS) {
Package pkg;
for (pkg = spec->packages; pkg; pkg = pkg->next) {
TFI_t fi = pkg->cpioList;
if (fi && fi->fc > 0)
break;
}
if (pkg == NULL)
continue;
}
// skip dotfiles in buildroot
if (fts->fts_level == 1 && *fts->fts_name == '.') {
if (fts->fts_info == FTS_D)
fts_set(ftsp, fts, FTS_SKIP);
continue;
}
// skip debuginfo
if (fts->fts_level == 3 && fts->fts_info == FTS_D) {
const char *dir = fts->fts_path + strlen(spec->buildRootURL);
if (strcmp(dir, "/usr/lib/debug") == 0 ||
strcmp(dir, "/usr/src/debug") == 0)
{
fts_set(ftsp, fts, FTS_SKIP);
continue;
}
}
switch (fts->fts_info) {
// do not check for unpackaged directories
case FTS_D:
case FTS_DP:
break;
case FTS_F:
case FTS_SL:
case FTS_SLNONE:
case FTS_DEFAULT:
check(fts->fts_path);
break;
default:
rpmlog(RPMLOG_WARNING, "%s: fts error\n", fts->fts_path);
rc |= 2;
break;
}
}
if (uv) {
rpmlog(RPMLOG_WARNING, "Installed (but unpackaged) file(s) found:\n");
qsort(uv, uc, sizeof(*uv), avcmp);
int i;
for (i = 0; i < uc; i++)
rpmlog(RPMLOG_INFO, " %s\n", uv[i]);
free(uv);
}
return rc;
}
int checkFiles(Spec spec)
{
checkIntersect(spec);
int rc = checkUnpackaged(spec);
if (rc && rpmExpandNumeric("%{?_unpackaged_files_terminate_build}")) {
rpmlog(RPMLOG_ERR, "File list check failed, terminating build\n");
return rc;
}
return 0;
}
// ex: set ts=8 sts=4 sw=4 noet: