Ejemplo n.º 1
0
Archivo: verify.c Proyecto: kaltsi/rpm
/**
 * Check file info from header against what's actually installed.
 * @param ts		transaction set
 * @param h		header to verify
 * @param omitMask	bits to disable verify checks
 * @param ghosts	should ghosts be verified?
 * @return		0 no problems, 1 problems found
 */
static int verifyHeader(rpmts ts, Header h, rpmVerifyAttrs omitMask, int ghosts)
{
    rpmVerifyAttrs verifyResult = 0;
    int ec = 0;		/* assume no problems */
    rpmfi fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_FLAGS_VERIFY);

    rpmfiInit(fi, 0);
    while (rpmfiNext(fi) >= 0) {
	rpmfileAttrs fileAttrs = rpmfiFFlags(fi);
	char *buf = NULL, *attrFormat;
	char ac;
	int rc;

	/* If not verifying %ghost, skip ghost files. */
	if ((fileAttrs & RPMFILE_GHOST) && !ghosts)
	    continue;

	rc = rpmVerifyFile(ts, fi, &verifyResult, omitMask);

	/* Filter out timestamp differences of shared files */
	if (rc == 0 && (verifyResult & RPMVERIFY_MTIME)) {
	    rpmdbMatchIterator mi;
	    mi = rpmtsInitIterator(ts, RPMDBI_BASENAMES, rpmfiFN(fi), 0);
	    if (rpmdbGetIteratorCount(mi) > 1) 
		verifyResult &= ~RPMVERIFY_MTIME;
	    rpmdbFreeIterator(mi);
	}

	attrFormat = rpmFFlagsString(fileAttrs, "");
	ac = rstreq(attrFormat, "") ? ' ' : attrFormat[0];
	if (rc) {
	    if (!(fileAttrs & (RPMFILE_MISSINGOK|RPMFILE_GHOST)) || rpmIsVerbose()) {
		rasprintf(&buf, _("missing   %c %s"), ac, rpmfiFN(fi));
		if ((verifyResult & RPMVERIFY_LSTATFAIL) != 0 &&
		    errno != ENOENT) {
		    char *app;
		    rasprintf(&app, " (%s)", strerror(errno));
		    rstrcat(&buf, app);
		    free(app);
		}
		ec = rc;
	    }
	} else if (verifyResult || rpmIsVerbose()) {
	    char *verifyFormat = rpmVerifyString(verifyResult, ".");
	    rasprintf(&buf, "%s  %c %s", verifyFormat, ac, rpmfiFN(fi));
	    free(verifyFormat);

	    if (verifyResult) ec = 1;
	}
	free(attrFormat);

	if (buf) {
	    rpmlog(RPMLOG_NOTICE, "%s\n", buf);
	    buf = _free(buf);
	}
    }
    rpmfiFree(fi);
	
    return ec;
}
Ejemplo n.º 2
0
static const char *matchFilesNext(matchFilesIter mfi)
{
    const char *matchFile = NULL;
    int fx = 0;

    /* Decide if we iterate over given files (mfi->files) */
    if (!mfi->ts)
	do {
	    /* Get next file from mfi->fi */
	    rpmfiNext(mfi->fi);
	    matchFile = rpmfiFN(mfi->fi);
	    if (strlen(matchFile))
		break;
	    matchFile = NULL;

	    /* If we are done with current mfi->fi, create mfi->fi for next prefix */
	    fx = rpmdsNext(mfi->rpmdsTrigger);
	    mfi->pfx = rpmdsN(mfi->rpmdsTrigger);
	    rpmfiFree(mfi->fi);
	    mfi->fi = rpmfilesFindPrefix(mfi->files, mfi->pfx);

	} while (fx >= 0);
    /* or we iterate over files in rpmdb */
    else
	do {
	    rpmfiNext(mfi->fi);
	    matchFile = rpmfiFN(mfi->fi);
	    if (strlen(matchFile))
		break;
	    matchFile = NULL;

	    /* If we are done with current mfi->fi, create mfi->fi for next package */
	    rpmfilesFree(mfi->files);
	    rpmfiFree(mfi->fi);
	    mfi->files = rpmtsNextFiles(mfi->ts, mfi->pi);
	    mfi->fi = rpmfilesFindPrefix(mfi->files, mfi->pfx);
	    if (mfi->files)
		continue;

	    /* If we are done with all packages, go through packages with new prefix */
	    fx = rpmdsNext(mfi->rpmdsTrigger);
	    mfi->pfx = rpmdsN(mfi->rpmdsTrigger);
	    rpmdbFreeIterator(mfi->pi);
	    mfi->pi = rpmdbInitPrefixIterator(rpmtsGetRdb(mfi->ts),
						RPMDBI_DIRNAMES, mfi->pfx, 0);

	    rpmdbFilterIterator(mfi->pi, mfi->tranPkgs, 0);

	} while (fx >= 0);


    return matchFile;
}
Ejemplo n.º 3
0
Archivo: ima.c Proyecto: maochaoyin/rpm
static rpmRC ima_psm_post(rpmPlugin plugin, rpmte te, int res)
{
	rpmfi fi = rpmteFI(te);
	const char *fpath;
	const unsigned char * fsig = NULL;
	size_t len;
	int rc = 0;

	if (fi == NULL) {
	    rc = RPMERR_BAD_MAGIC;
	    goto exit;
	}

	while (!rc) {
	    rc = rpmfiNext(fi);
	    if (rc < 0) {
		if (rc == RPMERR_ITER_END)
		    rc = 0;
		break;
	    }

	    /* Don't install signatures for (mutable) config files */
	    if (!(rpmfiFFlags(fi) & RPMFILE_CONFIG)) {
		fpath = rpmfiFN(fi);
		fsig = rpmfiFSignature(fi, &len);
		if (fsig) {
		    lsetxattr(fpath, XATTR_NAME_IMA, fsig, len, 0);
		}
	    }
	}
exit:
	return rc;
}
Ejemplo n.º 4
0
int mayAddToFilesAwaitingFiletriggers(const char * rootDir, rpmfi fi,
		int install_or_erase)
{
    const char * fn;
    FILE * fp;
    int rc = RPMRC_FAIL;
    int xx;

    if (filetriggers_dir() == NULL)
	return RPMRC_OK;

    fn = rpmGetPath(rootDir ? rootDir : "/", files_awaiting_filetriggers, NULL);

    fp = fopen(fn, "a");
    if (fp == NULL) {
	rpmlog(RPMLOG_ERR, _("%s: open failed: %s\n"), fn, strerror(errno));
	goto exit;
    }

    fi = rpmfiInit(fi, 0);
    if (fi != NULL)
    while (rpmfiNext(fi) >= 0) {
	xx = fputc(install_or_erase ? '+' : '-', fp);
	xx = fputs(rpmfiFN(fi), fp);
	xx = fputc('\n', fp);
    }
    xx = fclose(fp);
    rc = RPMRC_OK;

exit:
    fn = _free(fn);
    return rc;
}
Ejemplo n.º 5
0
/*@null@*/
static PyObject *
rpmfi_iternext(rpmfiObject * s)
	/*@globals _Py_NoneStruct @*/
	/*@modifies s, _Py_NoneStruct @*/
{
    PyObject * result = NULL;

    /* Reset loop indices on 1st entry. */
    if (!s->active) {
	s->fi = rpmfiInit(s->fi, 0);
	s->active = 1;
    }

    /* If more to do, return the file tuple. */
    if (rpmfiNext(s->fi) >= 0) {
	const char * FN = rpmfiFN(s->fi);
	int FSize = rpmfiFSize(s->fi);
	int FMode = rpmfiFMode(s->fi);
	int FMtime = rpmfiFMtime(s->fi);
	int FFlags = rpmfiFFlags(s->fi);
	int FRdev = rpmfiFRdev(s->fi);
	int FInode = rpmfiFInode(s->fi);
	int FNlink = rpmfiFNlink(s->fi);
	int FState = rpmfiFState(s->fi);
	int VFlags = rpmfiVFlags(s->fi);
	const char * FUser = rpmfiFUser(s->fi);
	const char * FGroup = rpmfiFGroup(s->fi);

	result = PyTuple_New(13);
	if (FN == NULL) {
	    Py_INCREF(Py_None);
	    PyTuple_SET_ITEM(result, 0, Py_None);
	} else
	    PyTuple_SET_ITEM(result,  0, Py_BuildValue("s", FN));
	PyTuple_SET_ITEM(result,  1, PyInt_FromLong(FSize));
	PyTuple_SET_ITEM(result,  2, PyInt_FromLong(FMode));
	PyTuple_SET_ITEM(result,  3, PyInt_FromLong(FMtime));
	PyTuple_SET_ITEM(result,  4, PyInt_FromLong(FFlags));
	PyTuple_SET_ITEM(result,  5, PyInt_FromLong(FRdev));
	PyTuple_SET_ITEM(result,  6, PyInt_FromLong(FInode));
	PyTuple_SET_ITEM(result,  7, PyInt_FromLong(FNlink));
	PyTuple_SET_ITEM(result,  8, PyInt_FromLong(FState));
	PyTuple_SET_ITEM(result,  9, PyInt_FromLong(VFlags));
	if (FUser == NULL) {
	    Py_INCREF(Py_None);
	    PyTuple_SET_ITEM(result, 10, Py_None);
	} else
	    PyTuple_SET_ITEM(result, 10, Py_BuildValue("s", FUser));
	if (FGroup == NULL) {
	    Py_INCREF(Py_None);
	    PyTuple_SET_ITEM(result, 11, Py_None);
	} else
	    PyTuple_SET_ITEM(result, 11, Py_BuildValue("s", FGroup));
	PyTuple_SET_ITEM(result, 12, rpmfi_Digest(s));
    } else
	s->active = 0;

    return result;
}
Ejemplo n.º 6
0
static VALUE
rpmfi_FN_get(VALUE s)
{
    rpmfi fi = rpmfi_ptr(s);
if (_debug)
fprintf(stderr, "==> %s(0x%lx) ptr %p\n", __FUNCTION__, s, fi);
    return rb_str_new2(rpmfiFN(fi));
}
Ejemplo n.º 7
0
/* XXX only ts->{probs,rpmdb} modified */
static void handleInstInstalledFile(const rpmts ts, rpmte p, rpmfi fi,
				   Header otherHeader, rpmfi otherFi,
				   int beingRemoved)
{
    unsigned int fx = rpmfiFX(fi);
    rpmfs fs = rpmteGetFileStates(p);
    int isCfgFile = ((rpmfiFFlags(otherFi) | rpmfiFFlags(fi)) & RPMFILE_CONFIG);

    if (XFA_SKIPPING(rpmfsGetAction(fs, fx)))
	return;

    if (rpmfiCompare(otherFi, fi)) {
	rpm_color_t tscolor = rpmtsColor(ts);
	rpm_color_t prefcolor = rpmtsPrefColor(ts);
	rpm_color_t FColor = rpmfiFColor(fi) & tscolor;
	rpm_color_t oFColor = rpmfiFColor(otherFi) & tscolor;
	int rConflicts;
	char rState = RPMFILE_STATE_REPLACED;

	rConflicts = !(beingRemoved || (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEOLDFILES));
	/* Resolve file conflicts to prefer Elf64 (if not forced). */
	if (tscolor != 0 && FColor != 0 && oFColor != 0 && FColor != oFColor) {
	    if (oFColor & prefcolor) {
		rpmfsSetAction(fs, fx, FA_SKIPCOLOR);
		rConflicts = 0;
	    } else if (FColor & prefcolor) {
		rpmfsSetAction(fs, fx, FA_CREATE);
		rConflicts = 0;
		rState = RPMFILE_STATE_WRONGCOLOR;
	    }
	}

	if (rConflicts) {
	    char *altNEVR = headerGetAsString(otherHeader, RPMTAG_NEVRA);
	    rpmteAddProblem(p, RPMPROB_FILE_CONFLICT, altNEVR, rpmfiFN(fi),
			    headerGetInstance(otherHeader));
	    free(altNEVR);
	}

	/* Save file identifier to mark as state REPLACED. */
	if ( !(isCfgFile || XFA_SKIPPING(rpmfsGetAction(fs, fx))) ) {
	    if (!beingRemoved)
		rpmfsAddReplaced(rpmteGetFileStates(p), rpmfiFX(fi), rState,
				 headerGetInstance(otherHeader),
				 rpmfiFX(otherFi));
	}
    }

    /* Determine config file dispostion, skipping missing files (if any). */
    if (isCfgFile) {
	int skipMissing = ((rpmtsFlags(ts) & RPMTRANS_FLAG_ALLFILES) ? 0 : 1);
	rpmFileAction action = rpmfiDecideFate(otherFi, fi, skipMissing);
	rpmfsSetAction(fs, fx, action);
    }
    rpmfiSetFReplacedSize(fi, rpmfiFSize(otherFi));
}
Ejemplo n.º 8
0
Archivo: rpmfi-py.c Proyecto: xrg/RPM
static int
rpmfi_print(rpmfiObject * s, FILE * fp, int flags)
{
    if (!(s && s->fi))
	return -1;

    s->fi = rpmfiInit(s->fi, 0);
    while (rpmfiNext(s->fi) >= 0)
	fprintf(fp, "%s\n", rpmfiFN(s->fi));
    return 0;
}
Ejemplo n.º 9
0
static int
rpmfi_print(rpmfiObject * s, FILE * fp, /*@unused@*/ int flags)
	/*@globals fileSystem @*/
	/*@modifies s, fp, fileSystem @*/
{
    if (!(s && s->fi))
	return -1;

    s->fi = rpmfiInit(s->fi, 0);
    while (rpmfiNext(s->fi) >= 0)
	fprintf(fp, "%s\n", rpmfiFN(s->fi));
    return 0;
}
Ejemplo n.º 10
0
static PyObject *
rpmfi_subscript(rpmfiObject * s, PyObject * key)
{
    int ix;

    if (!PyInt_Check(key)) {
	PyErr_SetString(PyExc_TypeError, "integer expected");
	return NULL;
    }

    ix = (int) PyInt_AsLong(key);
    rpmfiSetFX(s->fi, ix);
    return Py_BuildValue("s", rpmfiFN(s->fi));
}
Ejemplo n.º 11
0
Archivo: rpmfi.c Proyecto: akozumpl/rpm
int rpmfiConfigConflict(const rpmfi fi)
{
    const char * fn = rpmfiFN(fi);
    rpmfileAttrs flags = rpmfiFFlags(fi);
    char buffer[1024];
    rpmFileTypes newWhat, diskWhat;
    struct stat sb;

    if (!(flags & RPMFILE_CONFIG) || lstat(fn, &sb)) {
	return 0;
    }

    diskWhat = rpmfiWhatis((rpm_mode_t)sb.st_mode);
    newWhat = rpmfiWhatis(rpmfiFMode(fi));

    if (newWhat != LINK && newWhat != REG)
	return 1;

    if (diskWhat != newWhat)
	return 1;
    
    memset(buffer, 0, sizeof(buffer));
    if (newWhat == REG) {
	int algo;
	size_t diglen;
	const unsigned char *ndigest = rpmfiFDigest(fi, &algo, &diglen);
	if (rpmDoDigest(algo, fn, 0, (unsigned char *)buffer, NULL))
	    return 0;	/* assume file has been removed */
	if (ndigest && !memcmp(ndigest, buffer, diglen))
	    return 0;	/* unmodified config file */
    } else /* newWhat == LINK */ {
	const char * nFLink;
	ssize_t link_len = readlink(fn, buffer, sizeof(buffer) - 1);
	if (link_len == -1)
	    return 0;	/* assume file has been removed */
	buffer[link_len] = '\0';
	nFLink = rpmfiFLink(fi);
	if (nFLink && rstreq(nFLink, buffer))
	    return 0;	/* unmodified config file */
    }

    return 1;
}
Ejemplo n.º 12
0
static void checkInstFileDeps(rpmts ts, depCache dcache, rpmte te,
			      rpmTag depTag, rpmfi fi, int is_not,
			      filedepHash cache, fingerPrintCache *fpcp)
{
    fingerPrintCache fpc = *fpcp;
    fingerPrint * fp = NULL;
    const char *basename = rpmfiBN(fi);
    const char *dirname;
    const char **dirnames = 0;
    int ndirnames = 0;
    int i;

    filedepHashGetEntry(cache, basename, &dirnames, &ndirnames, NULL);
    if (!ndirnames)
	return;
    if (!fpc)
	*fpcp = fpc = fpCacheCreate(1001, NULL);
    dirname = rpmfiDN(fi);
    fpLookup(fpc, dirname, basename, &fp);
    for (i = 0; i < ndirnames; i++) {
	char *fpdep = 0;
	const char *dep;
	if (!strcmp(dirnames[i], dirname)) {
	    dep = rpmfiFN(fi);
	} else if (fpLookupEquals(fpc, fp, dirnames[i], basename)) {
	    fpdep = rmalloc(strlen(dirnames[i]) + strlen(basename) + 1);
	    strcpy(fpdep, dirnames[i]);
	    strcat(fpdep, basename);
	    dep = fpdep;
	} else {
	    continue;
	}
	if (!is_not)
	    checkInstDeps(ts, dcache, te, depTag, dep);
	else
	    checkNotInstDeps(ts, dcache, te, depTag, dep);
	_free(fpdep);
    }
    _free(fp);
}
Ejemplo n.º 13
0
string_list *
rpm_file_list(const char * pkg)
{
  rpmReadConfigFiles(NULL, NULL);
  FD_t fd = Fopen(pkg, "r.ufdio");

  rpmts ts = rpmtsCreate();
  Header h;
  rpmReadPackageFile(ts, fd, NULL, &h);
  rpmtsFree(ts);

  string_list * sl = string_list_new();
  rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER);

  if (fi) {
    while (rpmfiNext(fi) != -1) {
      string_list_append(sl, rpmfiFN(fi));
    }
    fi = rpmfiFree(fi);
  }

  return sl;
}
Ejemplo n.º 14
0
/*@null@*/
static PyObject *
rpmfi_FN(rpmfiObject * s)
	/*@modifies s @*/
{
    return Py_BuildValue("s", xstrdup(rpmfiFN(s->fi)));
}
Ejemplo n.º 15
0
static int process_package(rpmts ts, char * filename)
{
    FD_t fdi;
    FD_t gzdi;
    Header h;
    int rc = 0;
    char * rpmio_flags = NULL;
    struct archive *a;
    struct archive_entry *entry;

    if (!strcmp(filename, "-")) {
	fdi = fdDup(STDIN_FILENO);
    } else {
	fdi = Fopen(filename, "r.ufdio");
    }

    if (Ferror(fdi)) {
	fprintf(stderr, "rpm2archive: %s: %s\n",
		filename, Fstrerror(fdi));
	exit(EXIT_FAILURE);
    }

    rc = rpmReadPackageFile(ts, fdi, "rpm2cpio", &h);

    switch (rc) {
    case RPMRC_OK:
    case RPMRC_NOKEY:
    case RPMRC_NOTTRUSTED:
	break;
    case RPMRC_NOTFOUND:
	fprintf(stderr, _("argument is not an RPM package\n"));
	exit(EXIT_FAILURE);
	break;
    case RPMRC_FAIL:
    default:
	fprintf(stderr, _("error reading header from package\n"));
	exit(EXIT_FAILURE);
	break;
    }


    /* Retrieve payload size and compression type. */
    {	const char *compr = headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR);
	rpmio_flags = rstrscat(NULL, "r.", compr ? compr : "gzip", NULL);
    }

    gzdi = Fdopen(fdi, rpmio_flags);	/* XXX gzdi == fdi */
    free(rpmio_flags);

    if (gzdi == NULL) {
	fprintf(stderr, _("cannot re-open payload: %s\n"), Fstrerror(gzdi));
	exit(EXIT_FAILURE);
    }

    rpmfiles files = rpmfilesNew(NULL, h, 0, RPMFI_KEEPHEADER);
    rpmfi fi = rpmfiNewArchiveReader(gzdi, files, RPMFI_ITER_READ_ARCHIVE_CONTENT_FIRST);

    /* create archive */
    a = archive_write_new();
    archive_write_add_filter_gzip(a);
    archive_write_set_format_pax_restricted(a);

    if (!strcmp(filename, "-")) {
	if (isatty(STDOUT_FILENO)) {
	    fprintf(stderr, "Error: refusing to output archive data to a terminal.\n");
	    exit(EXIT_FAILURE);
	}
	archive_write_open_fd(a, STDOUT_FILENO);
    } else {
	char * outname = rstrscat(NULL, filename, ".tgz", NULL);
	archive_write_open_filename(a, outname);
	_free(outname);
	// XXX error handling
    }

    entry = archive_entry_new();

    char * buf = xmalloc(BUFSIZE);
    char * hardlink = NULL;

    rc = 0;
    while (rc >= 0) {
	rc = rpmfiNext(fi);
	if (rc == RPMERR_ITER_END) {
	    break;
	}

	rpm_mode_t mode = rpmfiFMode(fi);
	int nlink = rpmfiFNlink(fi);

	fill_archive_entry(a, entry, fi);

	if (nlink > 1) {
	    if (rpmfiArchiveHasContent(fi)) {
		_free(hardlink);
		hardlink = rstrscat(NULL, ".", rpmfiFN(fi), NULL);
	    } else {
		archive_entry_set_hardlink(entry, hardlink);
	    }
	}

	archive_write_header(a, entry);

	if (S_ISREG(mode) && (nlink == 1 || rpmfiArchiveHasContent(fi))) {
	    write_file_content(a, buf, fi);
	}
    }
    /* End of iteration is not an error */
    if (rc == RPMERR_ITER_END) {
	rc = 0;
    }

    _free(hardlink);

    Fclose(gzdi);	/* XXX gzdi == fdi */
    archive_entry_free(entry);
    archive_write_close(a);
    archive_write_free(a);
    buf = _free(buf);
    rpmfilesFree(files);
    rpmfiFree(fi);
    headerFree(h);
    return rc;
}
Ejemplo n.º 16
0
static PyObject *
rpmfi_FN(rpmfiObject * s, PyObject * unused)
{
    return Py_BuildValue("s", rpmfiFN(s->fi));
}
Ejemplo n.º 17
0
rpmFileAction rpmfiDecideFate(const rpmfi ofi, rpmfi nfi, int skipMissing)
{
    const char * fn = rpmfiFN(nfi);
    rpmfileAttrs newFlags = rpmfiFFlags(nfi);
    char buffer[1024];
    rpmFileTypes dbWhat, newWhat, diskWhat;
    struct stat sb;
    int save = (newFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SAVE;

    if (lstat(fn, &sb)) {
	/*
	 * The file doesn't exist on the disk. Create it unless the new
	 * package has marked it as missingok, or allfiles is requested.
	 */
	if (skipMissing && (newFlags & RPMFILE_MISSINGOK)) {
	    rpmlog(RPMLOG_DEBUG, "%s skipped due to missingok flag\n",
			fn);
	    return FA_SKIP;
	} else {
	    return FA_CREATE;
	}
    }

    diskWhat = rpmfiWhatis((rpm_mode_t)sb.st_mode);
    dbWhat = rpmfiWhatis(rpmfiFMode(ofi));
    newWhat = rpmfiWhatis(rpmfiFMode(nfi));

    /*
     * RPM >= 2.3.10 shouldn't create config directories -- we'll ignore
     * them in older packages as well.
     */
    if (newWhat == XDIR)
	return FA_CREATE;

    if (diskWhat != newWhat && dbWhat != REG && dbWhat != LINK)
	return save;
    else if (newWhat != dbWhat && diskWhat != dbWhat)
	return save;
    else if (dbWhat != newWhat)
	return FA_CREATE;
    else if (dbWhat != LINK && dbWhat != REG)
	return FA_CREATE;

    /*
     * This order matters - we'd prefer to CREATE the file if at all
     * possible in case something else (like the timestamp) has changed.
     */
    memset(buffer, 0, sizeof(buffer));
    if (dbWhat == REG) {
	pgpHashAlgo oalgo, nalgo;
	size_t odiglen, ndiglen;
	const unsigned char * odigest, * ndigest;
	odigest = rpmfiFDigest(ofi, &oalgo, &odiglen);
	if (diskWhat == REG) {
	    if (rpmDoDigest(oalgo, fn, 0, 
		(unsigned char *)buffer, NULL))
	        return FA_CREATE;	/* assume file has been removed */
	    if (odigest && !memcmp(odigest, buffer, odiglen))
	        return FA_CREATE;	/* unmodified config file, replace. */
	}
	ndigest = rpmfiFDigest(nfi, &nalgo, &ndiglen);
	/* Can't compare different hash types, backup to avoid data loss */
	if (oalgo != nalgo || odiglen != ndiglen)
	    return save;
	if (odigest && ndigest && !memcmp(odigest, ndigest, odiglen))
	    return FA_SKIP;	/* identical file, don't bother. */
    } else /* dbWhat == LINK */ {
	const char * oFLink, * nFLink;
	oFLink = rpmfiFLink(ofi);
	if (diskWhat == LINK) {
	    if (readlink(fn, buffer, sizeof(buffer) - 1) == -1)
		return FA_CREATE;	/* assume file has been removed */
	    if (oFLink && rstreq(oFLink, buffer))
		return FA_CREATE;	/* unmodified config file, replace. */
	}
	nFLink = rpmfiFLink(nfi);
	if (oFLink && nFLink && rstreq(oFLink, nFLink))
	    return FA_SKIP;	/* identical file, don't bother. */
    }

    /*
     * The config file on the disk has been modified, but
     * the ones in the two packages are different. It would
     * be nice if RPM was smart enough to at least try and
     * merge the difference ala CVS, but...
     */
    return save;
}
Ejemplo n.º 18
0
/* XXX only ts->{probs,di} modified */
static void handleOverlappedFiles(const rpmts ts, const rpmte p, rpmfi fi)
{
    rpm_loff_t fixupSize = 0;
    rpmps ps;
    const char * fn;
    int i, j;
    rpm_color_t tscolor = rpmtsColor(ts);
    rpm_color_t prefcolor = rpmtsPrefColor(ts);
    rpmfs fs = rpmteGetFileStates(p);
    rpmfs otherFs;

    ps = rpmtsProblems(ts);
    fi = rpmfiInit(fi, 0);
    if (fi != NULL)
    while ((i = rpmfiNext(fi)) >= 0) {
	rpm_color_t oFColor, FColor;
	struct fingerPrint_s * fiFps;
	int otherPkgNum, otherFileNum;
	rpmfi otherFi;
	rpmte otherTe;
	rpmfileAttrs FFlags;
	rpm_mode_t FMode;
	struct rpmffi_s * recs;
	int numRecs;

	if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
	    continue;

	fn = rpmfiFN(fi);
	fiFps = rpmfiFpsIndex(fi, i);
	FFlags = rpmfiFFlags(fi);
	FMode = rpmfiFMode(fi);
	FColor = rpmfiFColor(fi);
	FColor &= tscolor;

	fixupSize = 0;

	/*
	 * Retrieve all records that apply to this file. Note that the
	 * file info records were built in the same order as the packages
	 * will be installed and removed so the records for an overlapped
	 * files will be sorted in exactly the same order.
	 */
	(void) rpmFpHashGetEntry(ts->ht, fiFps, &recs, &numRecs, NULL);

	/*
	 * If this package is being added, look only at other packages
	 * being added -- removed packages dance to a different tune.
	 *
	 * If both this and the other package are being added, overlapped
	 * files must be identical (or marked as a conflict). The
	 * disposition of already installed config files leads to
	 * a small amount of extra complexity.
	 *
	 * If this package is being removed, then there are two cases that
	 * need to be worried about:
	 * If the other package is being added, then skip any overlapped files
	 * so that this package removal doesn't nuke the overlapped files
	 * that were just installed.
	 * If both this and the other package are being removed, then each
	 * file removal from preceding packages needs to be skipped so that
	 * the file removal occurs only on the last occurence of an overlapped
	 * file in the transaction set.
	 *
	 */

	/* Locate this overlapped file in the set of added/removed packages. */
	for (j = 0; j < numRecs && recs[j].p != p; j++)
	    {};

	/* Find what the previous disposition of this file was. */
	otherFileNum = -1;			/* keep gcc quiet */
	otherFi = NULL;
	otherTe = NULL;
	otherFs = NULL;

	for (otherPkgNum = j - 1; otherPkgNum >= 0; otherPkgNum--) {
	    otherTe = recs[otherPkgNum].p;
	    otherFi = rpmteFI(otherTe);
	    otherFileNum = recs[otherPkgNum].fileno;
	    otherFs = rpmteGetFileStates(otherTe);

	    /* Added packages need only look at other added packages. */
	    if (rpmteType(p) == TR_ADDED && rpmteType(otherTe) != TR_ADDED)
		continue;

	    (void) rpmfiSetFX(otherFi, otherFileNum);

	    /* XXX Happens iff fingerprint for incomplete package install. */
	    if (rpmfsGetAction(otherFs, otherFileNum) != FA_UNKNOWN);
		break;
	}

	oFColor = rpmfiFColor(otherFi);
	oFColor &= tscolor;

	switch (rpmteType(p)) {
	case TR_ADDED:
	  {
	    int reportConflicts =
		!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACENEWFILES);
	    int done = 0;

	    if (otherPkgNum < 0) {
		/* XXX is this test still necessary? */
		rpmFileAction action;
		if (rpmfsGetAction(fs, i) != FA_UNKNOWN)
		    break;
		if (rpmfiConfigConflict(fi)) {
		    /* Here is a non-overlapped pre-existing config file. */
		    action = (FFlags & RPMFILE_NOREPLACE) ?
			      FA_ALTNAME : FA_BACKUP;
		} else {
		    action = FA_CREATE;
		}
		rpmfsSetAction(fs, i, action);
		break;
	    }

assert(otherFi != NULL);
	    /* Mark added overlapped non-identical files as a conflict. */
	    if (rpmfiCompare(otherFi, fi)) {
		int rConflicts;

		rConflicts = reportConflicts;
		/* Resolve file conflicts to prefer Elf64 (if not forced) ... */
		if (tscolor != 0) {
		    if (FColor & prefcolor) {
			/* ... last file of preferred colour is installed ... */
			if (!XFA_SKIPPING(rpmfsGetAction(fs, i))) {
			    /* XXX static helpers are order dependent. Ick. */
			    if (strcmp(fn, "/usr/sbin/libgcc_post_upgrade")
			     && strcmp(fn, "/usr/sbin/glibc_post_upgrade"))
				rpmfsSetAction(otherFs, otherFileNum, FA_SKIPCOLOR);
			}
			rpmfsSetAction(fs, i, FA_CREATE);
			rConflicts = 0;
		    } else
		    if (oFColor & prefcolor) {
			/* ... first file of preferred colour is installed ... */
			if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
			    rpmfsSetAction(otherFs, otherFileNum, FA_CREATE);
			rpmfsSetAction(fs, i, FA_SKIPCOLOR);
			rConflicts = 0;
		    }
		    done = 1;
		}
		if (rConflicts) {
		    rpmpsAppend(ps, RPMPROB_NEW_FILE_CONFLICT,
			rpmteNEVRA(p), rpmteKey(p),
			fn, NULL,
			rpmteNEVRA(otherTe),
			0);
		}
	    }

	    /* Try to get the disk accounting correct even if a conflict. */
	    fixupSize = rpmfiFSize(otherFi);

	    if (rpmfiConfigConflict(fi)) {
		/* Here is an overlapped  pre-existing config file. */
		rpmFileAction action;
		action = (FFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SKIP;
		rpmfsSetAction(fs, i, action);
	    } else {
		if (!done)
		    rpmfsSetAction(fs, i, FA_CREATE);
	    }
	  } break;

	case TR_REMOVED:
	    if (otherPkgNum >= 0) {
		assert(otherFi != NULL);
                /* Here is an overlapped added file we don't want to nuke. */
		if (rpmfsGetAction(otherFs, otherFileNum) != FA_ERASE) {
		    /* On updates, don't remove files. */
		    rpmfsSetAction(fs, i, FA_SKIP);
		    break;
		}
		/* Here is an overlapped removed file: skip in previous. */
		rpmfsSetAction(otherFs, otherFileNum, FA_SKIP);
	    }
	    if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
		break;
	    if (rpmfiFState(fi) != RPMFILE_STATE_NORMAL)
		break;
	    if (!(S_ISREG(FMode) && (FFlags & RPMFILE_CONFIG))) {
		rpmfsSetAction(fs, i, FA_ERASE);
		break;
	    }
		
	    /* Here is a pre-existing modified config file that needs saving. */
	    {	pgpHashAlgo algo = 0;
		size_t diglen = 0;
		const unsigned char *digest;
		if ((digest = rpmfiFDigest(fi, &algo, &diglen))) {
		    unsigned char fdigest[diglen];
		    if (!rpmDoDigest(algo, fn, 0, fdigest, NULL) &&
			memcmp(digest, fdigest, diglen)) {
			rpmfsSetAction(fs, i, FA_BACKUP);
			break;
		    }
		}
	    }
	    rpmfsSetAction(fs, i, FA_ERASE);
	    break;
	}

	/* Update disk space info for a file. */
	rpmtsUpdateDSI(ts, fiFps->entry->dev, rpmfiFSize(fi),
		       rpmfiFReplacedSize(fi), fixupSize, rpmfsGetAction(fs, i));

    }
    ps = rpmpsFree(ps);
}
Ejemplo n.º 19
0
Archivo: verify.c Proyecto: xrg/RPM
/**
 * Check file info from header against what's actually installed.
 * @param qva		parsed query/verify options
 * @param ts		transaction set
 * @param h		header to verify
 * @return		0 no problems, 1 problems found
 */
static int verifyHeader(QVA_t qva, const rpmts ts, Header h)
{
    rpmVerifyAttrs verifyResult = 0;
    /* FIX: union? */
    rpmVerifyAttrs omitMask = ((qva->qva_flags & VERIFY_ATTRS) ^ VERIFY_ATTRS);
    int ec = 0;		/* assume no problems */
    char *buf = NULL;
    int i;

    rpmfi fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_FLAGS_VERIFY);
    rpmfiInit(fi, 0);
    while ((i = rpmfiNext(fi)) >= 0) {
	rpmfileAttrs fileAttrs;
	int rc;

	fileAttrs = rpmfiFFlags(fi);

	/* If not verifying %ghost, skip ghost files. */
	if (!(qva->qva_fflags & RPMFILE_GHOST)
	&& (fileAttrs & RPMFILE_GHOST))
	    continue;

	rc = rpmVerifyFile(ts, fi, &verifyResult, omitMask);
	if (rc) {
	    if (!(fileAttrs & (RPMFILE_MISSINGOK|RPMFILE_GHOST)) || rpmIsVerbose()) {
		rasprintf(&buf, _("missing   %c %s"),
			((fileAttrs & RPMFILE_CONFIG)	? 'c' :
			 (fileAttrs & RPMFILE_DOC)	? 'd' :
			 (fileAttrs & RPMFILE_GHOST)	? 'g' :
			 (fileAttrs & RPMFILE_LICENSE)	? 'l' :
			 (fileAttrs & RPMFILE_PUBKEY)	? 'P' :
			 (fileAttrs & RPMFILE_README)	? 'r' : ' '), 
			rpmfiFN(fi));
		if ((verifyResult & RPMVERIFY_LSTATFAIL) != 0 &&
		    errno != ENOENT) {
		    char *app;
		    rasprintf(&app, " (%s)", strerror(errno));
		    rstrcat(&buf, app);
		    free(app);
		}
		ec = rc;
	    }
	} else if (verifyResult || rpmIsVerbose()) {
	    const char * size, * MD5, * link, * mtime, * mode;
	    const char * group, * user, * rdev, *caps;
	    static const char *const aok = ".";
	    static const char *const unknown = "?";

	    ec = 1;

#define	_verify(_RPMVERIFY_F, _C)	\
	((verifyResult & _RPMVERIFY_F) ? _C : aok)
#define	_verifylink(_RPMVERIFY_F, _C)	\
	((verifyResult & RPMVERIFY_READLINKFAIL) ? unknown : \
	 (verifyResult & _RPMVERIFY_F) ? _C : aok)
#define	_verifyfile(_RPMVERIFY_F, _C)	\
	((verifyResult & RPMVERIFY_READFAIL) ? unknown : \
	 (verifyResult & _RPMVERIFY_F) ? _C : aok)
	
	    MD5 = _verifyfile(RPMVERIFY_MD5, "5");
	    size = _verify(RPMVERIFY_FILESIZE, "S");
	    link = _verifylink(RPMVERIFY_LINKTO, "L");
	    mtime = _verify(RPMVERIFY_MTIME, "T");
	    rdev = _verify(RPMVERIFY_RDEV, "D");
	    user = _verify(RPMVERIFY_USER, "U");
	    group = _verify(RPMVERIFY_GROUP, "G");
	    mode = _verify(RPMVERIFY_MODE, "M");
	    caps = _verify(RPMVERIFY_CAPS, "P");

#undef _verifyfile
#undef _verifylink
#undef _verify

	    rasprintf(&buf, "%s%s%s%s%s%s%s%s%s  %c %s",
			size, mode, MD5, rdev, link, user, group, mtime, caps,
			((fileAttrs & RPMFILE_CONFIG)	? 'c' :
			 (fileAttrs & RPMFILE_DOC)	? 'd' :
			 (fileAttrs & RPMFILE_GHOST)	? 'g' :
			 (fileAttrs & RPMFILE_LICENSE)	? 'l' :
			 (fileAttrs & RPMFILE_PUBKEY)	? 'P' :
			 (fileAttrs & RPMFILE_README)	? 'r' : ' '), 
			rpmfiFN(fi));
	}

	if (buf) {
	    rpmlog(RPMLOG_NOTICE, "%s\n", buf);
	    buf = _free(buf);
	}
    }
    rpmfiFree(fi);
	
    return ec;
}
Ejemplo n.º 20
0
Archivo: verify.c Proyecto: xrg/RPM
int rpmVerifyFile(const rpmts ts, const rpmfi fi,
		rpmVerifyAttrs * res, rpmVerifyAttrs omitMask)
{
    rpm_mode_t fmode = rpmfiFMode(fi);
    rpmfileAttrs fileAttrs = rpmfiFFlags(fi);
    rpmVerifyAttrs flags = rpmfiVFlags(fi);
    const char * fn = rpmfiFN(fi);
    struct stat sb;
    int rc;

    *res = RPMVERIFY_NONE;

    /*
     * Check to see if the file was installed - if not pretend all is OK.
     */
    switch (rpmfiFState(fi)) {
    case RPMFILE_STATE_NETSHARED:
    case RPMFILE_STATE_REPLACED:
    case RPMFILE_STATE_NOTINSTALLED:
    case RPMFILE_STATE_WRONGCOLOR:
	return 0;
	break;
    case RPMFILE_STATE_NORMAL:
	break;
    }

    if (fn == NULL || lstat(fn, &sb) != 0) {
	*res |= RPMVERIFY_LSTATFAIL;
	return 1;
    }

    /*
     * Not all attributes of non-regular files can be verified.
     */
    if (S_ISDIR(sb.st_mode))
	flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | 
			RPMVERIFY_LINKTO | RPMVERIFY_CAPS);
    else if (S_ISLNK(sb.st_mode)) {
	flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
			RPMVERIFY_MODE | RPMVERIFY_CAPS);
#if CHOWN_FOLLOWS_SYMLINK
	    flags &= ~(RPMVERIFY_USER | RPMVERIFY_GROUP);
#endif
    }
    else if (S_ISFIFO(sb.st_mode))
	flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | 
			RPMVERIFY_LINKTO | RPMVERIFY_CAPS);
    else if (S_ISCHR(sb.st_mode))
	flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | 
			RPMVERIFY_LINKTO | RPMVERIFY_CAPS);
    else if (S_ISBLK(sb.st_mode))
	flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | 
			RPMVERIFY_LINKTO | RPMVERIFY_CAPS);
    else 
	flags &= ~(RPMVERIFY_LINKTO);

    /*
     * Content checks of %ghost files are meaningless.
     */
    if (fileAttrs & RPMFILE_GHOST)
	flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | 
			RPMVERIFY_LINKTO);

    /*
     * Don't verify any features in omitMask.
     */
    flags &= ~(omitMask | RPMVERIFY_FAILURES);


    if (flags & RPMVERIFY_MD5) {
	const unsigned char *digest; 
	pgpHashAlgo algo;
	size_t diglen;

	/* XXX If --nomd5, then prelinked library sizes are not corrected. */
	if ((digest = rpmfiFDigest(fi, &algo, &diglen))) {
	    unsigned char fdigest[diglen];
	    rpm_loff_t fsize;

	    rc = rpmDoDigest(algo, fn, 0, fdigest, &fsize);
	    sb.st_size = fsize;
	    if (rc) {
		*res |= (RPMVERIFY_READFAIL|RPMVERIFY_MD5);
	    } else if (memcmp(fdigest, digest, diglen)) {
		*res |= RPMVERIFY_MD5;
	    }
	} else {
	    *res |= RPMVERIFY_MD5;
	} 
    } 

    if (flags & RPMVERIFY_LINKTO) {
	char linkto[1024+1];
	int size = 0;

	if ((size = readlink(fn, linkto, sizeof(linkto)-1)) == -1)
	    *res |= (RPMVERIFY_READLINKFAIL|RPMVERIFY_LINKTO);
	else {
	    const char * flink = rpmfiFLink(fi);
	    linkto[size] = '\0';
	    if (flink == NULL || strcmp(linkto, flink))
		*res |= RPMVERIFY_LINKTO;
	}
    } 

    if (flags & RPMVERIFY_FILESIZE) {
	if (sb.st_size != rpmfiFSize(fi))
	    *res |= RPMVERIFY_FILESIZE;
    } 

    if (flags & RPMVERIFY_MODE) {
	rpm_mode_t metamode = fmode;
	rpm_mode_t filemode;

	/*
	 * Platforms (like AIX) where sizeof(rpm_mode_t) != sizeof(mode_t)
	 * need the (rpm_mode_t) cast here. 
	 */
	filemode = (rpm_mode_t)sb.st_mode;

	/*
	 * Comparing the type of %ghost files is meaningless, but perms are OK.
	 */
	if (fileAttrs & RPMFILE_GHOST) {
	    metamode &= ~0xf000;
	    filemode &= ~0xf000;
	}

	if (metamode != filemode)
	    *res |= RPMVERIFY_MODE;

#if WITH_ACL
	/*
	 * For now, any non-default acl's on a file is a difference as rpm
	 * cannot have set them.
	 */
	acl_t facl = acl_get_file(fn, ACL_TYPE_ACCESS);
	if (facl) {
	    if (acl_equiv_mode(facl, NULL) == 1) {
		*res |= RPMVERIFY_MODE;
	    }
	    acl_free(facl);
	}
#endif 
    }

    if (flags & RPMVERIFY_RDEV) {
	if (S_ISCHR(fmode) != S_ISCHR(sb.st_mode)
	 || S_ISBLK(fmode) != S_ISBLK(sb.st_mode))
	{
	    *res |= RPMVERIFY_RDEV;
	} else if (S_ISDEV(fmode) && S_ISDEV(sb.st_mode)) {
	    rpm_rdev_t st_rdev = (sb.st_rdev & 0xffff);
	    rpm_rdev_t frdev = (rpmfiFRdev(fi) & 0xffff);
	    if (st_rdev != frdev)
		*res |= RPMVERIFY_RDEV;
	} 
    }

#if WITH_CAP
    if (flags & RPMVERIFY_CAPS) {
	/*
 	 * Empty capability set ("=") is not exactly the same as no
 	 * capabilities at all but suffices for now... 
 	 */
	cap_t cap, fcap;
	cap = cap_from_text(rpmfiFCaps(fi));
	if (!cap) {
	    cap = cap_from_text("=");
	}
	fcap = cap_get_file(fn);
	if (!fcap) {
	    fcap = cap_from_text("=");
	}
	
	if (cap_compare(cap, fcap) != 0)
	    *res |= RPMVERIFY_CAPS;

	cap_free(fcap);
	cap_free(cap);
    }
#endif

    if ((flags & RPMVERIFY_MTIME) && (sb.st_mtime != rpmfiFMtime(fi))) {
	/* Filter out timestamp differences of shared files */
	rpmdbMatchIterator mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, fn, 0);
	if (rpmdbGetIteratorCount(mi) < 2) 
	    *res |= RPMVERIFY_MTIME;
	rpmdbFreeIterator(mi);
    }

    if (flags & RPMVERIFY_USER) {
	const char * name = uidToUname(sb.st_uid);
	const char * fuser = rpmfiFUser(fi);
	if (name == NULL || fuser == NULL || strcmp(name, fuser))
	    *res |= RPMVERIFY_USER;
    }

    if (flags & RPMVERIFY_GROUP) {
	const char * name = gidToGname(sb.st_gid);
	const char * fgroup = rpmfiFGroup(fi);
	if (name == NULL || fgroup == NULL || strcmp(name, fgroup))
	    *res |= RPMVERIFY_GROUP;
    }

    return 0;
}
Ejemplo n.º 21
0
void genRpmPackageFiles(RowYield& yield, QueryContext& context) {
  auto dropper = DropPrivileges::get();
  if (!dropper->dropTo("nobody") && isUserAdmin()) {
    LOG(WARNING) << "Cannot drop privileges for rpm_package_files";
    return;
  }

  // Isolate RPM/package inspection to the canonical: /usr/lib/rpm.
  RpmEnvironmentManager env_manager;

  if (rpmReadConfigFiles(nullptr, nullptr) != 0) {
    TLOG << "Cannot read RPM configuration files";
    return;
  }

  rpmts ts = rpmtsCreate();
  rpmdbMatchIterator matches;
  if (context.constraints["package"].exists(EQUALS)) {
    auto name = (*context.constraints["package"].getAll(EQUALS).begin());
    matches = rpmtsInitIterator(ts, RPMTAG_NAME, name.c_str(), name.size());
  } else {
    matches = rpmtsInitIterator(ts, RPMTAG_NAME, nullptr, 0);
  }

  Header header;
  while ((header = rpmdbNextIterator(matches)) != nullptr) {
    rpmtd td = rpmtdNew();
    rpmfi fi = rpmfiNew(ts, header, RPMTAG_BASENAMES, RPMFI_NOHEADER);
    std::string package_name = getRpmAttribute(header, RPMTAG_NAME, td);

    auto file_count = rpmfiFC(fi);
    if (file_count <= 0) {
      VLOG(1) << "RPM package " << package_name << " contains 0 files";
      rpmfiFree(fi);
      continue;
    } else if (file_count > MAX_RPM_FILES) {
      VLOG(1) << "RPM package " << package_name << " contains over "
              << MAX_RPM_FILES << " files";
      rpmfiFree(fi);
      continue;
    }

    // Iterate over every file in this package.
    for (size_t i = 0; rpmfiNext(fi) >= 0 && i < file_count; i++) {
      Row r;
      auto path = rpmfiFN(fi);
      r["package"] = package_name;
      r["path"] = (path != nullptr) ? path : "";
      auto username = rpmfiFUser(fi);
      r["username"] = (username != nullptr) ? username : "";
      auto groupname = rpmfiFGroup(fi);
      r["groupname"] = (groupname != nullptr) ? groupname : "";
      r["mode"] = lsperms(rpmfiFMode(fi));
      r["size"] = BIGINT(rpmfiFSize(fi));

      int digest_algo;
      auto digest = rpmfiFDigestHex(fi, &digest_algo);
      if (digest_algo == PGPHASHALGO_SHA256) {
        r["sha256"] = (digest != nullptr) ? digest : "";
      }

      yield(r);
    }

    rpmfiFree(fi);
    rpmtdFree(td);
  }

  rpmdbFreeIterator(matches);
  rpmtsFree(ts);
  rpmFreeRpmrc();
}
Ejemplo n.º 22
0
QueryData genRpmPackageFiles(QueryContext& context) {
  QueryData results;
  if (rpmReadConfigFiles(nullptr, nullptr) != 0) {
    TLOG << "Cannot read RPM configuration files.";
    return results;
  }

  rpmts ts = rpmtsCreate();
  rpmdbMatchIterator matches;
  if (context.constraints["package"].exists()) {
    auto name = (*context.constraints["package"].getAll(EQUALS).begin());
    matches = rpmtsInitIterator(ts, RPMTAG_NAME, name.c_str(), name.size());
  } else {
    matches = rpmtsInitIterator(ts, RPMTAG_NAME, nullptr, 0);
  }

  Header header;
  while ((header = rpmdbNextIterator(matches)) != nullptr) {
    rpmtd td = rpmtdNew();
    rpmfi fi = rpmfiNew(ts, header, RPMTAG_BASENAMES, RPMFI_NOHEADER);
    auto file_count = rpmfiFC(fi);
    if (file_count <= 0 || file_count > MAX_RPM_FILES) {
      // This package contains no or too many files.
      rpmfiFree(fi);
      continue;
    }

    // Iterate over every file in this package.
    for (size_t i = 0; rpmfiNext(fi) >= 0 && i < file_count; i++) {
      Row r;
      r["package"] = getRpmAttribute(header, RPMTAG_NAME, td);
      auto path = rpmfiFN(fi);
      r["path"] = (path != nullptr) ? path : "";
      auto username = rpmfiFUser(fi);
      r["username"] = (username != nullptr) ? username : "";
      auto groupname = rpmfiFGroup(fi);
      r["groupname"] = (groupname != nullptr) ? groupname : "";
      r["mode"] = lsperms(rpmfiFMode(fi));
      r["size"] = BIGINT(rpmfiFSize(fi));

#ifdef CENTOS_CENTOS6
      // Older versions of rpmlib/rpmip use a hash algorithm enum.
      pgpHashAlgo digest_algo;
#else
      int digest_algo;
#endif
      auto digest = rpmfiFDigestHex(fi, &digest_algo);
      if (digest_algo == PGPHASHALGO_SHA256) {
        r["sha256"] = (digest != nullptr) ? digest : "";
      }

      results.push_back(r);
    }

    rpmfiFree(fi);
    rpmtdFree(td);
  }

  rpmdbFreeIterator(matches);
  rpmtsFree(ts);
  rpmFreeRpmrc();

  return results;
}
Ejemplo n.º 23
0
Archivo: rpmfi-py.c Proyecto: xrg/RPM
static PyObject *
rpmfi_FN(rpmfiObject * s)
{
    return Py_BuildValue("s", xstrdup(rpmfiFN(s->fi)));
}
Ejemplo n.º 24
0
static int rpmverify_collect(probe_ctx *ctx,
                             const char *name, oval_operation_t name_op,
                             const char *file, oval_operation_t file_op,
			     SEXP_t *name_ent, SEXP_t *filepath_ent,
                             uint64_t flags,
                             void (*callback)(probe_ctx *, struct rpmverify_res *))
{
	rpmdbMatchIterator match;
        rpmVerifyAttrs omit = (rpmVerifyAttrs)(flags & RPMVERIFY_RPMATTRMASK);
	Header pkgh;
        pcre *re = NULL;
	int  ret = -1;

        /* pre-compile regex if needed */
        if (file_op == OVAL_OPERATION_PATTERN_MATCH) {
                const char *errmsg;
                int erroff;

                re = pcre_compile(file, PCRE_UTF8, &errmsg,  &erroff, NULL);

                if (re == NULL) {
                        /* TODO */
                        return (-1);
                }
        }

        RPMVERIFY_LOCK;

        switch (name_op) {
        case OVAL_OPERATION_EQUALS:
                match = rpmtsInitIterator (g_rpm.rpmts, RPMTAG_NAME, (const void *)name, 0);

                if (match == NULL) {
                        ret = 0;
                        goto ret;
                }

                ret = rpmdbGetIteratorCount (match);

                break;
	case OVAL_OPERATION_NOT_EQUAL:
                match = rpmtsInitIterator (g_rpm.rpmts, RPMDBI_PACKAGES, NULL, 0);

                if (match == NULL) {
                        ret = 0;
                        goto ret;
                }

                if (rpmdbSetIteratorRE (match, RPMTAG_NAME, RPMMIRE_GLOB, "*") != 0)
                {
                        ret = -1;
                        goto ret;
                }

                break;
        case OVAL_OPERATION_PATTERN_MATCH:
                match = rpmtsInitIterator (g_rpm.rpmts, RPMDBI_PACKAGES, NULL, 0);

                if (match == NULL) {
                        ret = 0;
                        goto ret;
                }

                if (rpmdbSetIteratorRE (match, RPMTAG_NAME, RPMMIRE_REGEX,
                                        (const char *)name) != 0)
                {
                        ret = -1;
                        goto ret;
                }

                break;
        default:
                /* not supported */
                dE("package name: operation not supported");
                ret = -1;
                goto ret;
        }

	assume_d(RPMTAG_BASENAMES != 0, -1);
	assume_d(RPMTAG_DIRNAMES  != 0, -1);

        while ((pkgh = rpmdbNextIterator (match)) != NULL) {
                rpmfi  fi;
		rpmTag tag[2] = { RPMTAG_BASENAMES, RPMTAG_DIRNAMES };
                struct rpmverify_res res;
                errmsg_t rpmerr;
		int i;
		SEXP_t *name_sexp;

                res.name = headerFormat(pkgh, "%{NAME}", &rpmerr);

		name_sexp = SEXP_string_newf("%s", res.name);
		if (probe_entobj_cmp(name_ent, name_sexp) != OVAL_RESULT_TRUE) {
			SEXP_free(name_sexp);
			continue;
		}
		SEXP_free(name_sexp);

                /*
                 * Inspect package files & directories
                 */
		for (i = 0; i < 2; ++i) {
		  fi = rpmfiNew(g_rpm.rpmts, pkgh, tag[i], 1);

		  while (rpmfiNext(fi) != -1) {
		    SEXP_t *filepath_sexp;

		    res.fflags = rpmfiFFlags(fi);
		    res.oflags = omit;

		    if (((res.fflags & RPMFILE_CONFIG) && (flags & RPMVERIFY_SKIP_CONFIG)) ||
			((res.fflags & RPMFILE_GHOST)  && (flags & RPMVERIFY_SKIP_GHOST)))
		      continue;

		    res.file   = strdup(rpmfiFN(fi));

		    filepath_sexp = SEXP_string_newf("%s", res.file);
		    if (probe_entobj_cmp(filepath_ent, filepath_sexp) != OVAL_RESULT_TRUE) {
		      SEXP_free(filepath_sexp);
		      free(res.file);
		      continue;
		    }
		    SEXP_free(filepath_sexp);

		    if (rpmVerifyFile(g_rpm.rpmts, fi, &res.vflags, omit) != 0)
		      res.vflags = RPMVERIFY_FAILURES;

		    callback(ctx, &res);
		    free(res.file);
		  }

		  rpmfiFree(fi);
		}
	}

	match = rpmdbFreeIterator (match);
        ret   = 0;
ret:
        if (re != NULL)
                pcre_free(re);

        RPMVERIFY_UNLOCK;
        return (ret);
}
Ejemplo n.º 25
0
Archivo: verify.c Proyecto: nforro/rpm
/**
 * Check file info from header against what's actually installed.
 * @param ts		transaction set
 * @param h		header to verify
 * @param omitMask	bits to disable verify checks
 * @param incAttr	skip files without these attrs (eg %ghost)
 * @param skipAttr	skip files with these attrs (eg %ghost)
 * @return		0 no problems, 1 problems found
 */
static int verifyHeader(rpmts ts, Header h, rpmVerifyAttrs omitMask,
			rpmfileAttrs incAttrs, rpmfileAttrs skipAttrs)
{
    rpmVerifyAttrs verifyResult = 0;
    rpmVerifyAttrs verifyAll = 0; /* assume no problems */
    rpmfi fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_FLAGS_VERIFY);

    if (fi == NULL)
	return 1;

    rpmfiInit(fi, 0);
    while (rpmfiNext(fi) >= 0) {
	rpmfileAttrs fileAttrs = rpmfiFFlags(fi);
	char *buf = NULL, *attrFormat;
	const char *fstate = NULL;
	char ac;

	/* If filtering by inclusion, skip non-matching (eg --configfiles) */
	if (incAttrs && !(incAttrs & fileAttrs))
	    continue;

	/* Skip on attributes (eg from --noghost) */
	if (skipAttrs & fileAttrs)
	    continue;

	verifyResult = rpmfiVerify(fi, omitMask);

	/* Filter out timestamp differences of shared files */
	if (verifyResult & RPMVERIFY_MTIME) {
	    rpmdbMatchIterator mi;
	    mi = rpmtsInitIterator(ts, RPMDBI_BASENAMES, rpmfiFN(fi), 0);
	    if (rpmdbGetIteratorCount(mi) > 1) 
		verifyResult &= ~RPMVERIFY_MTIME;
	    rpmdbFreeIterator(mi);
	}

	/* State is only meaningful for installed packages */
	if (headerGetInstance(h))
	    fstate = stateStr(rpmfiFState(fi));

	attrFormat = rpmFFlagsString(fileAttrs, "");
	ac = rstreq(attrFormat, "") ? ' ' : attrFormat[0];
	if (verifyResult & RPMVERIFY_LSTATFAIL) {
	    if (!(fileAttrs & (RPMFILE_MISSINGOK|RPMFILE_GHOST)) || rpmIsVerbose()) {
		rasprintf(&buf, _("missing   %c %s"), ac, rpmfiFN(fi));
		if ((verifyResult & RPMVERIFY_LSTATFAIL) != 0 &&
		    errno != ENOENT) {
		    char *app;
		    rasprintf(&app, " (%s)", strerror(errno));
		    rstrcat(&buf, app);
		    free(app);
		}
	    }
	} else if (verifyResult || fstate || rpmIsVerbose()) {
	    char *verifyFormat = rpmVerifyString(verifyResult, ".");
	    rasprintf(&buf, "%s  %c %s", verifyFormat, ac, rpmfiFN(fi));
	    free(verifyFormat);
	}
	free(attrFormat);

	if (buf) {
	    if (fstate)
		buf = rstrscat(&buf, " (", fstate, ")", NULL);
	    rpmlog(RPMLOG_NOTICE, "%s\n", buf);
	    buf = _free(buf);
	}
	verifyAll |= verifyResult;
    }
    rpmfiFree(fi);
	
    return (verifyAll != 0) ? 1 : 0;
}
Ejemplo n.º 26
0
int rpmtsCheck(rpmts ts)
{
    rpm_color_t tscolor = rpmtsColor(ts);
    rpmtsi pi = NULL; rpmte p;
    int closeatexit = 0;
    int rc = 0;
    depCache dcache = NULL;
    conflictsCache confcache = NULL;
    
    (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_CHECK), 0);

    /* Do lazy, readonly, open of rpm database. */
    if (rpmtsGetRdb(ts) == NULL && rpmtsGetDBMode(ts) != -1) {
	if ((rc = rpmtsOpenDB(ts, rpmtsGetDBMode(ts))) != 0)
	    goto exit;
	closeatexit = 1;
    }

    /* XXX FIXME: figure some kind of heuristic for the cache size */
    dcache = depCacheCreate(5001, rstrhash, strcmp,
				     (depCacheFreeKey)rfree, NULL);

    confcache = conflictsCacheCreate(257, rstrhash, strcmp,
				     (depCacheFreeKey)rfree);
    if (confcache) {
	rpmdbIndexIterator ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), RPMTAG_CONFLICTNAME);
	if (ii) {
	    char *key;
	    size_t keylen;
	    while ((rpmdbIndexIteratorNext(ii, (const void**)&key, &keylen)) == 0) {
		char *k;
		if (!key || keylen == 0 || key[0] != '/')
		    continue;
		k = rmalloc(keylen + 1);
		memcpy(k, key, keylen);
		k[keylen] = 0;
		conflictsCacheAddEntry(confcache, k);
	    }
	    rpmdbIndexIteratorFree(ii);
	}
    }

    
    /*
     * Look at all of the added packages and make sure their dependencies
     * are satisfied.
     */
    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
	rpmds provides = rpmdsInit(rpmteDS(p, RPMTAG_PROVIDENAME));

	rpmlog(RPMLOG_DEBUG, "========== +++ %s %s/%s 0x%x\n",
		rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));

	checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_REQUIRENAME),
		NULL, tscolor);
	checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_CONFLICTNAME),
		NULL, tscolor);
	checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_OBSOLETENAME),
		NULL, tscolor);

	/* Check provides against conflicts in installed packages. */
	while (rpmdsNext(provides) >= 0) {
	    checkInstDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, rpmdsN(provides));
	}

	/* Skip obsoletion checks for source packages (ie build) */
	if (rpmteIsSource(p))
	    continue;

	/* Check package name (not provides!) against installed obsoletes */
	checkInstDeps(ts, dcache, p, RPMTAG_OBSOLETENAME, rpmteN(p));

	/* Check filenames against installed conflicts */
        if (conflictsCacheNumKeys(confcache)) {
	    rpmfi fi = rpmfiInit(rpmteFI(p), 0);
	    while (rpmfiNext(fi) >= 0) {
		const char *fn = rpmfiFN(fi);
		if (!conflictsCacheHasEntry(confcache, fn))
		    continue;
		checkInstDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, fn);
	    }
	}
    }
    rpmtsiFree(pi);

    /*
     * Look at the removed packages and make sure they aren't critical.
     */
    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
	rpmds provides = rpmdsInit(rpmteDS(p, RPMTAG_PROVIDENAME));
	rpmfi fi = rpmfiInit(rpmteFI(p), 0);

	rpmlog(RPMLOG_DEBUG, "========== --- %s %s/%s 0x%x\n",
		rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));

	/* Check provides and filenames against installed dependencies. */
	while (rpmdsNext(provides) >= 0) {
	    checkInstDeps(ts, dcache, p, RPMTAG_REQUIRENAME, rpmdsN(provides));
	}

	while (rpmfiNext(fi) >= 0) {
	    if (RPMFILE_IS_INSTALLED(rpmfiFState(fi)))
		checkInstDeps(ts, dcache, p, RPMTAG_REQUIRENAME, rpmfiFN(fi));
	}
    }
    rpmtsiFree(pi);

exit:
    depCacheFree(dcache);
    conflictsCacheFree(confcache);

    (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_CHECK), 0);

    if (closeatexit)
	(void) rpmtsCloseDB(ts);
    return rc;
}