[pacman-dev] [PATCH] Write mtree of package files to local database

Allan McRae allan at archlinux.org
Tue Feb 21 23:02:27 EST 2012


When installing a package, write an mtree of the package files into
the local database.  This will be useful for doing validation of all
files on a system.

Signed-off-by: Allan McRae <allan at archlinux.org>
---

Query: should we keep the info on .INSTALL and .CHANGELOG files?  Changing a
.INSTALL file would be an interesting tactic, but if someone is doing that then
they can already adjust the mtree file...

Also, from http://goo.gl/Uq6X5 it appears that this could be made more efficient
by reusing the file descriptor, but I could not get that working after many, many,
many attempts.

 lib/libalpm/add.c |   68 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 68 insertions(+), 0 deletions(-)

diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index b007766..31313a7 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -449,6 +449,68 @@ needbackup_cleanup:
 	return errors;
 }
 
+static int write_package_mtree(alpm_handle_t *handle, alpm_pkg_t *pkg, const char *file)
+{
+	char *path;
+	struct archive *archive, *mtree;
+	struct archive_entry *entry;
+	struct stat buf;
+	char buffer[ALPM_BUFFER_SIZE];
+	int fd, ret = 0, read = 0;
+
+	_alpm_log(handle, ALPM_LOG_DEBUG, "creating package mtree\n");
+
+	fd = _alpm_open_archive(handle, file, &buf,
+			&archive, ALPM_ERR_PKG_OPEN);
+	if(fd < 0) {
+		ret = ALPM_ERR_PKG_OPEN;
+		goto error;
+	}
+
+	if((mtree = archive_write_new()) == NULL) {
+		ret = ALPM_ERR_LIBARCHIVE;
+		archive_read_finish(archive);
+		goto error;
+	}
+
+	archive_write_set_format_mtree(mtree);
+	archive_write_set_compression_gzip(mtree);
+
+	/* output the type, uid, gid, mode, size, time, md5 and link fields */
+	archive_write_set_options(mtree, "use-set,!device,!flags,!gname,!nlink,!uname,md5");
+
+	path = _alpm_local_db_pkgpath(handle->db_local, pkg, "files.mtree");
+
+	if(archive_write_open_filename(mtree, path) != ARCHIVE_OK) {
+		_alpm_log(handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"),
+				path, archive_error_string(archive));
+		ret =  ALPM_ERR_DB_WRITE;
+		goto cleanup;
+	}
+
+	while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) {
+		const char *entryname = archive_entry_pathname(entry);
+		if(*entryname != '.') {
+			archive_write_header(mtree, entry);
+			while ((read = archive_read_data(archive, &buffer, ALPM_BUFFER_SIZE)) > 0) {
+				archive_write_data(mtree, buffer, read);
+			}
+		}
+	}
+
+cleanup:
+	archive_read_finish(archive);
+	archive_write_finish(mtree);
+	free(path);
+
+	if(ret == 0) {
+		return 0;
+	}
+
+error:
+	RET_ERR(handle, ret, -1);
+}
+
 static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
 		size_t pkg_current, size_t pkg_count)
 {
@@ -589,6 +651,12 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
 		archive_read_finish(archive);
 		CLOSE(fd);
 
+		if(write_package_mtree(handle, newpkg, pkgfile) == -1)
+		{
+			_alpm_log(handle, ALPM_LOG_WARNING,
+				_("could not create mtree file (%s)\n"), alpm_strerror(handle->pm_errno));
+		}
+
 		/* restore the old cwd if we have it */
 		if(cwdfd >= 0) {
 			if(fchdir(cwdfd) != 0) {
-- 
1.7.9.1



More information about the pacman-dev mailing list