[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[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: