Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Add support for writing a METALOG file instead of setting permissions.
Brad Davis committed 9 years ago
commit 8885bf4b5424ebb1a6009554a27bb6b9e0c1b494
parent cfa8b01
6 files changed +188 -12
modified libpkg/Makefile.am
@@ -27,6 +27,7 @@ libpkg_la_SOURCES= pkg.c \
			dns_utils.c \
			fetch.c \
			packing.c \
+
			metalog.c \
			pkg_add.c \
			pkg_arch.c \
			pkg_attributes.c \
added libpkg/metalog.c
@@ -0,0 +1,65 @@
+
/*-
+
 * Copyright (c) 2016 Brad Davis <brd@FreeBSD.org>
+
 * All rights reserved.
+
 * 
+
 * Redistribution and use in source and binary forms, with or without
+
 * modification, are permitted provided that the following conditions
+
 * are met:
+
 * 1. Redistributions of source code must retain the above copyright
+
 *    notice, this list of conditions and the following disclaimer
+
 *    in this position and unchanged.
+
 * 2. Redistributions in binary form must reproduce the above copyright
+
 *    notice, this list of conditions and the following disclaimer in the
+
 *    documentation and/or other materials provided with the distribution.
+
 * 
+
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
 */
+

+

+

+
#include "pkg.h"
+
#include "private/pkg.h"
+
#include "private/event.h"
+

+
FILE *metalogfp = NULL;
+

+
int
+
metalog_open(const char *metalog)
+
{
+
	metalogfp = fopen(metalog, "a");
+
	if (metalogfp == NULL) {
+
		pkg_emit_errno("Unable to open metalog: %s", metalog);
+
		return EPKG_FATAL;
+
	} 
+

+
	return EPKG_OK;
+
}
+

+
int
+
metalog_add(const char *metalogentry)
+
{
+
	if (metalogfp == NULL) {
+
		return EPKG_FATAL;
+
	}
+

+
	fprintf(metalogfp, "%s\n", metalogentry);
+

+
	return EPKG_OK;
+
}
+

+
void
+
metalog_close()
+
{
+
	if (metalogfp != NULL) {
+
		fclose(metalogfp);
+
	}
+
}
modified libpkg/pkg_add.c
@@ -320,6 +320,7 @@ do_extract_dir(struct pkg* pkg, struct archive *a __unused, struct archive_entry
	const struct stat *aest;
	struct stat st;
	unsigned long clear;
+
	char *metalogentry = NULL;

	d = pkg_get_dir(pkg, path);
	if (d == NULL) {
@@ -351,9 +352,16 @@ do_extract_dir(struct pkg* pkg, struct archive *a __unused, struct archive_entry
			return (EPKG_FATAL);
		}
	}
-
	if (st.st_uid == d->uid && st.st_gid == d->gid &&
-
	    (st.st_mode & S_IFMT) == (d->perm & S_IFMT)) {
-
		d->noattrs = true;
+

+
	asprintf(&metalogentry,
+
	   "./%s type=dir uname=%s gname=%s mode=%3o",
+
	   RELATIVE_PATH(path), archive_entry_uname(ae),
+
	   archive_entry_gname(ae), aest->st_mode & ~S_IFDIR);
+
	if (metalog_add(metalogentry) != EPKG_OK) {
+
		if (st.st_uid == d->uid && st.st_gid == d->gid &&
+
		    (st.st_mode & S_IFMT) == (d->perm & S_IFMT)) {
+
			d->noattrs = true;
+
		}
	}

	return (EPKG_OK);
@@ -369,6 +377,7 @@ do_extract_symlink(struct pkg *pkg, struct archive *a __unused, struct archive_e
	unsigned long clear;
	struct timespec tspec[2];
	bool tried_mkdir = false;
+
	char *metalogentry = NULL;

	f = pkg_get_file(pkg, path);
	if (f == NULL) {
@@ -397,11 +406,18 @@ retry:

	fill_timespec_buf(aest, tspec);

-
	if (set_attrs(pkg->rootfd, f->temppath, aest->st_mode,
-
	    get_uid_from_archive(ae), get_gid_from_archive(ae),
-
	    &tspec[0], &tspec[1]) != EPKG_OK) {
-
		return (EPKG_FATAL);
+
	asprintf(&metalogentry,
+
	   "./%s type=link uname=%s gname=%s mode=%3o link=%s",
+
	   RELATIVE_PATH(path), archive_entry_uname(ae),
+
	   archive_entry_gname(ae), aest->st_mode & ~S_IFLNK, archive_entry_symlink(ae));
+
	if (metalog_add(metalogentry) != EPKG_OK) {
+
		if (set_attrs(pkg->rootfd, f->temppath, aest->st_mode,
+
		    get_uid_from_archive(ae), get_gid_from_archive(ae),
+
		    &tspec[0], &tspec[1]) != EPKG_OK) {
+
			return (EPKG_FATAL);
+
		}
	}
+

	return (EPKG_OK);
}

@@ -410,8 +426,10 @@ do_extract_hardlink(struct pkg *pkg, struct archive *a __unused, struct archive_
    const char *path, struct pkg *local __unused)
{
	struct pkg_file *f, *fh;
+
	const struct stat *aest;
	const char *lp;
	bool tried_mkdir = false;
+
	char *metalogentry = NULL;

	f = pkg_get_file(pkg, path);
	if (f == NULL) {
@@ -427,6 +445,12 @@ do_extract_hardlink(struct pkg *pkg, struct archive *a __unused, struct archive_
	}

	pkg_hidden_tempfile(f->temppath, sizeof(f->temppath), path);
+
	aest = archive_entry_stat(ae);
+
	asprintf(&metalogentry, "./%s type=file uname=%s gname=%s mode=%3o",
+
	   RELATIVE_PATH(path), archive_entry_uname(ae),
+
	   archive_entry_gname(ae), aest->st_mode & ~S_IFREG);
+
	if (metalog_add(metalogentry) != EPKG_OK) {
+
	}
retry:
	if (linkat(pkg->rootfd, RELATIVE_PATH(fh->temppath),
	    pkg->rootfd, RELATIVE_PATH(f->temppath), 0) == -1) {
@@ -456,6 +480,7 @@ do_extract_regfile(struct pkg *pkg, struct archive *a, struct archive_entry *ae,
	size_t len;
	struct timespec tspec[2];
	bool tried_mkdir = false;
+
	char *metalogentry = NULL;

	f = pkg_get_file(pkg, path);
	if (f == NULL) {
@@ -517,11 +542,16 @@ retry:

	fill_timespec_buf(aest, tspec);

-
	if (set_attrs(pkg->rootfd, f->temppath, aest->st_mode,
-
	    get_uid_from_archive(ae), get_gid_from_archive(ae),
-
	    &tspec[0], &tspec[1]) != EPKG_OK)
-
		return (EPKG_FATAL);
-
	return (EPKG_OK);
+
	asprintf(&metalogentry, "./%s type=file uname=%s gname=%s mode=%3o",
+
	   RELATIVE_PATH(path), archive_entry_uname(ae),
+
	   archive_entry_gname(ae), aest->st_mode & ~S_IFREG);
+
	if (metalog_add(metalogentry) != EPKG_OK) {
+
		if (set_attrs(pkg->rootfd, f->temppath, aest->st_mode,
+
		    get_uid_from_archive(ae), get_gid_from_archive(ae),
+
		    &tspec[0], &tspec[1]) != EPKG_OK)
+
			return (EPKG_FATAL);
+
		return (EPKG_OK);
+
	}
}

static int
modified libpkg/pkg_config.c
@@ -403,6 +403,12 @@ static struct config_entry c[] = {
		"1048576", /* 1 meg */
		"Ask user when performing changes for more than this limit"
	},
+
	{
+
		PKG_STRING,
+
		"METALOG",
+
		NULL,
+
		"Write out the METALOG to the specified file",
+
	},
};

static bool parsed = false;
@@ -817,6 +823,7 @@ pkg_ini(const char *path, const char *reposdir, pkg_init_flags flags)
	const char *buf, *walk, *value, *key, *k;
	const char *evkey = NULL;
	const char *nsname = NULL;
+
	const char *metalog = NULL;
	const char *useragent = NULL;
	const char *evpipe = NULL;
	const char *url;
@@ -1173,6 +1180,14 @@ pkg_ini(const char *path, const char *reposdir, pkg_init_flags flags)
	if (nsname != NULL && set_nameserver(nsname) != 0)
			pkg_emit_error("Unable to set nameserver, ignoring");

+
	/* Open metalog */
+
	metalog = pkg_object_string(pkg_config_get("METALOG"));
+
	if (metalog != NULL) {
+
		if(metalog_open(metalog) != EPKG_OK) {
+
			return (EPKG_FATAL);
+
		}
+
	}
+

	return (EPKG_OK);
}

modified libpkg/private/pkg.h
@@ -794,4 +794,8 @@ int pkg_message_from_str(struct pkg *pkg, const char *str, size_t len);
ucl_object_t* pkg_message_to_ucl(const struct pkg *pkg);
char* pkg_message_to_str(struct pkg *pkg);

+
int metalog_open(const char *metalog);
+
int metalog_add();
+
void metalog_close();
+

#endif
modified tests/frontend/install.sh
@@ -3,10 +3,71 @@
. $(atf_get_srcdir)/test_environment.sh

tests_init \
+
	metalog \
	reinstall \
	pre_script_fail \
	post_script_ignored

+
metalog_body()
+
{
+
	new_pkg test test 1 / || atf_fail "Failed to create the ucl file"
+
	touch ${TMPDIR}/testfile1 || atf_fail "Failed to create the temp file"
+
	echo "@(root,wheel,640,) testfile1" > test.plist
+
	echo "test123" > ${TMPDIR}/testfile2 || atf_fail "Failed to create the temp file"
+
	echo "@(daemon,nobody,644,) testfile2" >> test.plist
+
	ln -s ${TMPDIR}/testfile1 ${TMPDIR}/testlink1
+
	echo "@ testlink1" >> test.plist
+
	ln ${TMPDIR}/testfile2 ${TMPDIR}/testhlink2
+
	echo "@ testhlink2" >> test.plist
+
	mkdir ${TMPDIR}/testdir1  || atf_fail "Failed to create the temp dir"
+
	echo "@dir testdir1" >> test.plist
+
	mkdir ${TMPDIR}/testdir2  || atf_fail "Failed to create the temp dir"
+
	chmod 750 ${TMPDIR}/testdir2 || atf_fail "Failed to chmod the temp dir"
+
	echo "@dir(daemon) testdir2" >> test.plist
+

+
	atf_check \
+
		-o ignore \
+
		-e empty \
+
		-s exit:0 \
+
		pkg create -r ${TMPDIR} -M test.ucl -p test.plist
+

+
	atf_check \
+
		-o ignore \
+
		-e empty \
+
		-s exit:0 \
+
		pkg repo .
+

+
	cat << EOF > repo.conf
+
local: {
+
	url: file:///${TMPDIR},
+
	enabled: true
+
}
+
EOF
+

+
	atf_check \
+
		-o ignore \
+
		-e empty \
+
		-s exit:0 \
+
		mkdir ${TMPDIR}/root
+

+
	atf_check \
+
		-o ignore \
+
		-e empty \
+
		-s exit:0 \
+
		pkg -o REPOS_DIR="${TMPDIR}" -o METALOG=${TMPDIR}/METALOG -r ${TMPDIR}/root install -y test
+

+
	atf_check \
+
		-o match:"./testfile1 type=file uname=root gname=wheel mode=640" \
+
		-o match:"./testfile2 type=file uname=daemon gname=nobody mode=644" \
+
		-o match:"./testlink1 type=link uname=root gname=wheel mode=755 link=${TMPDIR}/testfile1" \
+
		-o match:"./testhlink2 type=file uname=root gname=wheel mode=644" \
+
		-o match:"./testdir1 type=dir uname=root gname=wheel mode=755" \
+
		-o match:"./testdir2 type=dir uname=daemon gname=wheel mode=750" \
+
		-e empty \
+
		-s exit:0 \
+
		cat ${TMPDIR}/METALOG
+
}
+

reinstall_body()
{
	new_pkg test test 1 /usr/local