[PATCH 5/5] Add support for writing out extended attributes
From: Matthew Garrett <matthew.garrett@google.com>
Parse any mtree file present in control.tar.gz and attempt to write any
extended attributes. Ignore any failures caused by the filesystem not
having extended attribute support.
---
src/Makefile.am | 1 +
src/archives.c | 15 +++++++++++
src/filesdb.c | 1 +
src/filesdb.h | 9 +++++++
src/unpack.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 94 insertions(+)
diff --git a/src/Makefile.am b/src/Makefile.am
index 2d776dd9a..89a013b57 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,6 +7,7 @@ AM_CPPFLAGS = \
-DLOCALEDIR=\"$(localedir)\" \
-DADMINDIR=\"$(admindir)\" \
-idirafter $(top_srcdir)/lib/compat \
+ -idirafter $(top_srcdir)/lib/mtree \
-I$(top_builddir) \
-I$(top_srcdir)/lib
LDADD = \
diff --git a/src/archives.c b/src/archives.c
index 113b76c3d..22ef85eb3 100644
--- a/src/archives.c
+++ b/src/archives.c
@@ -41,6 +41,8 @@
#define obstack_chunk_alloc m_malloc
#define obstack_chunk_free free
+#include <attr/xattr.h>
+
#include <dpkg/i18n.h>
#include <dpkg/dpkg.h>
#include <dpkg/dpkg-db.h>
@@ -353,6 +355,7 @@ tarobject_extract(struct tarcontext *tc, struct tar_entry *te,
char fnamebuf[256];
char fnamenewbuf[256];
char *newhash;
+ int ret, i;
switch (te->type) {
case TAR_FILETYPE_FILE:
@@ -388,6 +391,18 @@ tarobject_extract(struct tarcontext *tc, struct tar_entry *te,
namenode->statoverride->uid,
namenode->statoverride->gid,
namenode->statoverride->mode);
+
+ /* Attempt to set any extended attributes.If the output filesystem
+ * doesn't support xattrs, skip it silently. */
+ if (namenode->xattr_num) {
+ for (i = 0; i < namenode->xattr_num; i++) {
+ struct dpkg_xattr *xattr = &namenode->xattrs[i];
+ ret = fsetxattr(fd, xattr->name, xattr->val, xattr->len, 0);
+ if (ret < 0 && errno != ENOTSUP)
+ ohshite(_("error setting IMA attribute of '%.255s'"), te->name);
+ }
+ }
+
if (fchown(fd, st->uid, st->gid))
ohshite(_("error setting ownership of '%.255s'"), te->name);
if (fchmod(fd, st->mode & ~S_IFMT))
diff --git a/src/filesdb.c b/src/filesdb.c
index 7f157727d..e7b35f1f4 100644
--- a/src/filesdb.c
+++ b/src/filesdb.c
@@ -632,6 +632,7 @@ struct filenamenode *findnamenode(const char *name, enum fnnflags flags) {
newnode->newhash = EMPTYHASHFLAG;
newnode->filestat = NULL;
newnode->trig_interested = NULL;
+ newnode->xattr_num = 0;
*pointerp= newnode;
nfiles++;
diff --git a/src/filesdb.h b/src/filesdb.h
index 954d67bd8..3f0b4c50d 100644
--- a/src/filesdb.h
+++ b/src/filesdb.h
@@ -77,6 +77,12 @@ enum filenamenode_flags {
fnnf_filtered = DPKG_BIT(9),
};
+struct dpkg_xattr {
+ char *name;
+ char *val;
+ unsigned int len;
+};
+
struct filenamenode {
struct filenamenode *next;
const char *name;
@@ -106,6 +112,9 @@ struct filenamenode {
struct stat *filestat;
struct trigfileint *trig_interested;
+
+ struct dpkg_xattr *xattrs;
+ int xattr_num;
};
struct fileinlist {
diff --git a/src/unpack.c b/src/unpack.c
index f43c01e45..2668a5e32 100644
--- a/src/unpack.c
+++ b/src/unpack.c
@@ -28,6 +28,8 @@
#include <sys/stat.h>
#include <sys/wait.h>
+#include <mtree.h>
+
#include <errno.h>
#include <string.h>
#include <time.h>
@@ -316,6 +318,68 @@ pkg_deconfigure_others(struct pkginfo *pkg)
}
}
+static void
+walk_mtree(NODE *mtree)
+{
+ struct filenamenode *namenode;
+ NODE *old;
+ int i;
+
+ while (mtree) {
+ if (mtree->child)
+ walk_mtree(mtree->child);
+
+ namenode = findnamenode(mtree->name, 0);
+ if (namenode) {
+ if (mtree->xattr_num) {
+ namenode->xattrs = malloc(mtree->xattr_num * sizeof(struct dpkg_xattr));
+ for (i=0; i<mtree->xattr_num; i++) {
+ struct dpkg_xattr *xattr = &namenode->xattrs[i];
+ xattr->name = strdup(mtree->xattrs[i].name);
+ xattr->val = base64_decode(mtree->xattrs[i].value, &xattr->len);
+ }
+ }
+ namenode->xattr_num = mtree->xattr_num;
+ }
+ old = mtree;
+ mtree = mtree->next;
+ free(old->md5digest);
+ free(old->slink);
+ free(old);
+ }
+}
+
+/**
+ *
+ * Read the mtree data
+ */
+static void
+deb_parse_mtree(struct pkginfo *pkg, const char *control_mtree)
+{
+ FILE *mtreef;
+ NODE *mtreedata;
+
+ mtreef = fopen(control_mtree, "r");
+ if (mtreef == NULL) {
+ if (errno == ENOENT)
+ return;
+ ohshite(_("error trying to open %.250s"), control_mtree);
+ }
+
+ push_cleanup(cu_closestream, ehflag_bombout, NULL, 0, 1, mtreef);
+
+ mtreedata = mtree_readspec(mtreef);
+
+ pop_cleanup(ehflag_normaltidy); /* mtreef = fopen() */
+ if (fclose(mtreef))
+ ohshite(_("error closing %.250s"), control_mtree);
+
+ if (!mtreedata)
+ return;
+
+ walk_mtree(mtreedata);
+}
+
/**
* Read the conffiles, and copy the hashes across.
*/
@@ -1212,6 +1276,10 @@ void process_archive(const char *filename) {
strcpy(cidirrest, TRIGGERSCIFILE);
trig_parse_ci(cidir, NULL, trig_cicb_statuschange_activate, pkg, &pkg->available);
+ /* Parse the mtree metadata. */
+ strcpy(cidirrest,MTREEFILE);
+ deb_parse_mtree(pkg, cidir);
+
/* Read the conffiles, and copy the hashes across. */
newconffiles.head = NULL;
newconffiles.tail = &newconffiles.head;
--
2.17.0.441.gb46fe60e1d-goog
Reply to: