Ejemplo n.º 1
0
int rpmfiCompareIndex(rpmfi afi, int aix, rpmfi bfi, int bix)
{
    mode_t amode = rpmfiFModeIndex(afi, aix);
    mode_t bmode = rpmfiFModeIndex(bfi, bix);
    rpmFileTypes awhat = rpmfiWhatis(amode);

    if ((rpmfiFFlagsIndex(afi, aix) & RPMFILE_GHOST) ||
	(rpmfiFFlagsIndex(bfi, bix) & RPMFILE_GHOST)) return 0;

    /* Mode difference is a conflict, except for symlinks */
    if (!(awhat == LINK && rpmfiWhatis(bmode) == LINK) && amode != bmode)
	return 1;

    if (awhat == LINK || awhat == REG) {
	if (rpmfiFSizeIndex(afi, aix) != rpmfiFSizeIndex(bfi, bix))
	    return 1;
    }

    if (!rstreq(rpmfiFUserIndex(afi, aix), rpmfiFUserIndex(bfi, bix)))
	return 1;
    if (!rstreq(rpmfiFGroupIndex(afi, aix), rpmfiFGroupIndex(bfi, bix)))
	return 1;

    if (awhat == LINK) {
	const char * alink = rpmfiFLinkIndex(afi, aix);
	const char * blink = rpmfiFLinkIndex(bfi, bix);
	if (alink == blink) return 0;
	if (alink == NULL) return 1;
	if (blink == NULL) return -1;
	return strcmp(alink, blink);
    } else if (awhat == REG) {
	size_t adiglen, bdiglen;
	int aalgo, balgo;
	const unsigned char * adigest, * bdigest;
	adigest = rpmfiFDigestIndex(afi, aix, &aalgo, &adiglen);
	bdigest = rpmfiFDigestIndex(bfi, bix, &balgo, &bdiglen);
	if (adigest == bdigest) return 0;
	if (adigest == NULL) return 1;
	if (bdigest == NULL) return -1;
	/* can't meaningfully compare different hash types */
	if (aalgo != balgo || adiglen != bdiglen) return -1;
	return memcmp(adigest, bdigest, adiglen);
    } else if (awhat == CDEV || awhat == BDEV) {
	if (rpmfiFRdevIndex(afi, aix) != rpmfiFRdevIndex(bfi, bix))
	    return 1;
    }

    return 0;
}
Ejemplo n.º 2
0
int rpmfiConfigConflictIndex(rpmfi fi, int ix)
{
    const char * fn = rpmfiFNIndex(fi, ix);
    rpmfileAttrs flags = rpmfiFFlagsIndex(fi, ix);
    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(rpmfiFModeIndex(fi, ix));

    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 = rpmfiFDigestIndex(fi,ix, &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 = rpmfiFLinkIndex(fi, ix);
	if (nFLink && rstreq(nFLink, buffer))
	    return 0;	/* unmodified config file */
    }

    return 1;
}
Ejemplo n.º 3
0
rpmFileAction rpmfiDecideFateIndex(rpmfi ofi, int oix, rpmfi nfi, int nix,
				   int skipMissing)
{
    const char * fn = rpmfiFNIndex(nfi, nix);
    rpmfileAttrs newFlags = rpmfiFFlagsIndex(nfi, nix);
    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(rpmfiFModeIndex(ofi, oix));
    newWhat = rpmfiWhatis(rpmfiFModeIndex(nfi, nix));

    /*
     * 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) {
	int oalgo, nalgo;
	size_t odiglen, ndiglen;
	const unsigned char * odigest, * ndigest;
	odigest = rpmfiFDigestIndex(ofi, oix, &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 = rpmfiFDigestIndex(nfi, nix, &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 = rpmfiFLinkIndex(ofi, oix);
	if (diskWhat == LINK) {
	    ssize_t link_len = readlink(fn, buffer, sizeof(buffer) - 1);
	    if (link_len == -1)
		return FA_CREATE;	/* assume file has been removed */
	    buffer[link_len] = '\0';
	    if (oFLink && rstreq(oFLink, buffer))
		return FA_CREATE;	/* unmodified config file, replace. */
	}
	nFLink = rpmfiFLinkIndex(nfi, nix);
	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.º 4
0
int rpmfiConfigConflictIndex(rpmfi fi, int ix)
{
    char * fn = NULL;
    rpmfileAttrs flags = rpmfiFFlagsIndex(fi, ix);
    char buffer[1024];
    rpmFileTypes newWhat, diskWhat;
    struct stat sb;
    int rc = 0;

    /* Non-configs are not config conflicts. */
    if (!(flags & RPMFILE_CONFIG))
	return 0;

    /* Only links and regular files can be %config, this is kinda moot */
    /* XXX: Why are we returning 1 here? */
    newWhat = rpmfiWhatis(rpmfiFModeIndex(fi, ix));
    if (newWhat != LINK && newWhat != REG)
	return 1;

    /* If it's not on disk, there's nothing to be saved */
    fn = rpmfiFNIndex(fi, ix);
    if (lstat(fn, &sb))
	goto exit;

    /*
     * Preserve legacy behavior: an existing %ghost %config is considered
     * "modified" but unlike regular %config, its never removed and
     * never backed up. Whether this actually makes sense is a whole
     * another question, but this is very long-standing behavior that
     * people might be depending on. The resulting FA_ALTNAME etc action
     * is special-cased in FSM to avoid actually creating backups on ghosts.
     */
    if (flags & RPMFILE_GHOST) {
	rc = 1;
	goto exit;
    }

    /* Files of different types obviously are not identical */
    diskWhat = rpmfiWhatis((rpm_mode_t)sb.st_mode);
    if (diskWhat != newWhat) {
	rc = 1;
	goto exit;
    }

    /* Files of different sizes obviously are not identical */
    if (rpmfiFSizeIndex(fi, ix) != sb.st_size) {
	rc = 1;
	goto exit;
    }
    
    memset(buffer, 0, sizeof(buffer));
    if (newWhat == REG) {
	int algo;
	size_t diglen;
	const unsigned char *ndigest = rpmfiFDigestIndex(fi,ix, &algo, &diglen);
	if (rpmDoDigest(algo, fn, 0, (unsigned char *)buffer, NULL))
	    goto exit;	/* assume file has been removed */
	if (ndigest && memcmp(ndigest, buffer, diglen) == 0)
	    goto exit;	/* unmodified config file */
    } else /* newWhat == LINK */ {
	const char * nFLink;
	ssize_t link_len = readlink(fn, buffer, sizeof(buffer) - 1);
	if (link_len == -1)
	    goto exit;	/* assume file has been removed */
	buffer[link_len] = '\0';
	nFLink = rpmfiFLinkIndex(fi, ix);
	if (nFLink && rstreq(nFLink, buffer))
	    goto exit;	/* unmodified config file */
    }

    rc = 1;

exit:
    free(fn);
    return rc;
}
Ejemplo n.º 5
0
rpmFileAction rpmfiDecideFateIndex(rpmfi ofi, int oix, rpmfi nfi, int nix,
				   int skipMissing)
{
    char * fn = rpmfiFNIndex(nfi, nix);
    rpmfileAttrs newFlags = rpmfiFFlagsIndex(nfi, nix);
    char buffer[1024];
    rpmFileTypes dbWhat, newWhat, diskWhat;
    struct stat sb;
    int save = (newFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SAVE;
    int action = FA_CREATE; /* assume we can create */

    /* If the new file is a ghost, leave whatever might be on disk alone. */
    if (newFlags & RPMFILE_GHOST) {
	action = FA_SKIP;
	goto exit;
    }

    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);
	    action = FA_SKIP;
	    goto exit;
	} else {
	    goto exit;
	}
    }

    diskWhat = rpmfiWhatis((rpm_mode_t)sb.st_mode);
    dbWhat = rpmfiWhatis(rpmfiFModeIndex(ofi, oix));
    newWhat = rpmfiWhatis(rpmfiFModeIndex(nfi, nix));

    /*
     * This order matters - we'd prefer to CREATE the file if at all
     * possible in case something else (like the timestamp) has changed.
     * Only regular files and symlinks might need a backup, everything
     * else falls through here with FA_CREATE.
     */
    memset(buffer, 0, sizeof(buffer));
    if (dbWhat == REG) {
	int oalgo, nalgo;
	size_t odiglen, ndiglen;
	const unsigned char * odigest, * ndigest;

	/* See if the file on disk is identical to the one in old pkg */
	odigest = rpmfiFDigestIndex(ofi, oix, &oalgo, &odiglen);
	if (diskWhat == REG) {
	    if (rpmDoDigest(oalgo, fn, 0, (unsigned char *)buffer, NULL))
	        goto exit;	/* assume file has been removed */
	    if (odigest && memcmp(odigest, buffer, odiglen) == 0)
	        goto exit;	/* unmodified config file, replace. */
	}

	/* See if the file on disk is identical to the one in new pkg */
	ndigest = rpmfiFDigestIndex(nfi, nix, &nalgo, &ndiglen);
	if (diskWhat == REG && newWhat == REG) {
	    /* hash algo changed in new, recalculate digest */
	    if (oalgo != nalgo)
		if (rpmDoDigest(nalgo, fn, 0, (unsigned char *)buffer, NULL))
		    goto exit;		/* assume file has been removed */
	    if (ndigest && memcmp(ndigest, buffer, ndiglen) == 0)
	        goto exit;		/* file identical in new, replace. */
	}

	/* If file can be determined identical in old and new pkg, let it be */
	if (newWhat == REG && oalgo == nalgo && odiglen == ndiglen) {
	    if (odigest && ndigest && memcmp(odigest, ndigest, odiglen) == 0) {
		action = FA_SKIP; /* identical file, dont bother */
		goto exit;
	    }
	}
	
	/* ...but otherwise a backup will be needed */
	action = save;
    } else if (dbWhat == LINK) {
	const char * oFLink, * nFLink;

	/* See if the link on disk is identical to the one in old pkg */
	oFLink = rpmfiFLinkIndex(ofi, oix);
	if (diskWhat == LINK) {
	    ssize_t link_len = readlink(fn, buffer, sizeof(buffer) - 1);
	    if (link_len == -1)
		goto exit;		/* assume file has been removed */
	    buffer[link_len] = '\0';
	    if (oFLink && rstreq(oFLink, buffer))
		goto exit;		/* unmodified config file, replace. */
	}

	/* See if the link on disk is identical to the one in new pkg */
	nFLink = rpmfiFLinkIndex(nfi, nix);
	if (diskWhat == LINK && newWhat == LINK) {
	    if (nFLink && rstreq(nFLink, buffer))
		goto exit;		/* unmodified config file, replace. */
	}

	/* If link is identical in old and new pkg, let it be */
	if (newWhat == LINK && oFLink && nFLink && rstreq(oFLink, nFLink)) {
	    action = FA_SKIP;		/* identical file, don't bother. */
	    goto exit;
	}

	/* ...but otherwise a backup will be needed */
	action = save;
    }

exit:
    free(fn);
    return action;
}