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

Re: Review of file exclusion branch requested



* Guillem Jover 

| Thanks for working on this. For next time please use
| git-format-patch, it makes it easier to review, also it allows one
| to fix the patches and resend.

Git branch updated and restructured patches attached; I believe I have
addressed all your comments.

Still missing:

- Documentation
- I believe there might be a bug where the filters code does not
  respect --root passed to dpkg; I need to test that and possibly fix
  it.

-- 
Tollef Fog Heen
UNIX is user friendly, it's just picky about who its friends are
>From 3eb1d13d1cddcd0af7fe477b09468c5184eb1a50 Mon Sep 17 00:00:00 2001
From: Tollef Fog Heen <tfheen@err.no>
Date: Wed, 2 Apr 2008 23:19:51 +0200
Subject: [PATCH] Move "skip a file forward" into its own function

---
 src/archives.c |   39 +++++++++++++++++++++++++--------------
 1 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/src/archives.c b/src/archives.c
index 023678f..f653831 100644
--- a/src/archives.c
+++ b/src/archives.c
@@ -230,6 +230,30 @@ int tarfileread(void *ud, char *buf, int len) {
   return r;
 }
 
+void tarfile_skip_one_forward(struct TarInfo *ti, 
+			      struct fileinlist **oldnifd,
+			      struct fileinlist *nifd) {
+  struct tarcontext *tc= (struct tarcontext*)ti->UserData;
+  size_t r;
+  char databuf[TARBLKSZ];
+
+  obstack_free(&tar_obs, nifd);
+  tc->newfilesp= oldnifd;
+  *oldnifd = NULL;
+
+  /* We need to advance the tar file to the next object, so read the
+   * file data and set it to oblivion.
+   */
+  if ((ti->Type == NormalFile0) || (ti->Type == NormalFile1)) {
+    char fnamebuf[256];
+    fd_null_copy(tc->backendpipe, ti->Size, 
+		 "skipped unpacking file `%.255s' (replaced or excluded?)", 
+		 quote_filename(fnamebuf,256,ti->Name));
+    r= ti->Size % TARBLKSZ;
+    if (r > 0) r= safe_read(tc->backendpipe,databuf,TARBLKSZ - r);
+  }
+}
+
 int fnameidlu;
 struct varbuf fnamevb;
 struct varbuf fnametmpvb;
@@ -584,20 +608,7 @@ int tarobject(struct TarInfo *ti) {
 
   if (existingdirectory) return 0;
   if (keepexisting) {
-    obstack_free(&tar_obs, nifd);
-    tc->newfilesp= oldnifd;
-    *oldnifd = NULL;
-
-    /* We need to advance the tar file to the next object, so read the
-     * file data and set it to oblivion.
-     */
-    if ((ti->Type == NormalFile0) || (ti->Type == NormalFile1)) {
-      char fnamebuf[256];
-      fd_null_copy(tc->backendpipe, ti->Size, _("gobble replaced file `%.255s'"),quote_filename(fnamebuf,256,ti->Name));
-      r= ti->Size % TARBLKSZ;
-      if (r > 0) r= safe_read(tc->backendpipe,databuf,TARBLKSZ - r);
-    }
-
+    tarfile_skip_one_forward(ti, oldnifd, nifd);
     return 0;
   }
 
-- 
1.5.4.3

>From 6947a549a0d89369c41e975360991277f3d18058 Mon Sep 17 00:00:00 2001
From: Tollef Fog Heen <tfheen@err.no>
Date: Thu, 3 Apr 2008 08:21:56 +0200
Subject: [PATCH] Add support for excluding bits of packages as they are unpacked.

---
 src/Makefile.am |    4 +-
 src/archives.c  |   10 ++++
 src/filters.c   |  155 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/filters.h   |   32 +++++++++++
 src/main.c      |    3 +
 5 files changed, 203 insertions(+), 1 deletions(-)
 create mode 100644 src/filters.c
 create mode 100644 src/filters.h

diff --git a/src/Makefile.am b/src/Makefile.am
index a1377e7..c347988 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,6 +4,7 @@ localedir = $(datadir)/locale
 INCLUDES = \
 	-DLOCALEDIR=\"$(localedir)\" \
 	-DADMINDIR=\"$(admindir)\" \
+	-DCONFIGDIR=\"$(pkgconfdir)\" \
 	-idirafter $(top_srcdir)/libcompat \
 	-I$(top_srcdir)/lib
 
@@ -25,7 +26,8 @@ dpkg_SOURCES = \
 	remove.c \
 	select.c \
 	trigproc.c \
-	update.c
+	update.c \
+	filters.c filters.h
 
 dpkg_LDADD = \
 	../libcompat/libcompat.a \
diff --git a/src/archives.c b/src/archives.c
index f653831..6e04142 100644
--- a/src/archives.c
+++ b/src/archives.c
@@ -52,6 +52,7 @@ static security_context_t scontext    = NULL;
 #include "filesdb.h"
 #include "main.h"
 #include "archives.h"
+#include "filters.h"
 
 #define MAXCONFLICTORS 20
 
@@ -393,6 +394,8 @@ static int linktosameexistingdir(const struct TarInfo *ti,
   return 1;
 }
 
+extern struct filterlist *filters;
+
 int tarobject(struct TarInfo *ti) {
   static struct varbuf conffderefn, hardlinkfn, symlinkfn;
   static int fd;
@@ -430,6 +433,13 @@ int tarobject(struct TarInfo *ti) {
         nifd->namenode->divert && nifd->namenode->divert->useinstead
         ? nifd->namenode->divert->useinstead->name : "<none>");
 
+  if (filter_should_skip(ti) == 1) {
+    struct filenamenode *fnn = findnamenode(ti->Name, 0);
+    fnn->flags &= ~fnnf_new_inarchive;
+    tarfile_skip_one_forward(ti, oldnifd, nifd);
+    return 0;
+  }
+
   if (nifd->namenode->divert && nifd->namenode->divert->camefrom) {
     divpkg= nifd->namenode->divert->pkg;
 
diff --git a/src/filters.c b/src/filters.c
new file mode 100644
index 0000000..c9032f5
--- /dev/null
+++ b/src/filters.c
@@ -0,0 +1,155 @@
+/*
+ * dpkg - main program for package management
+ * filters.c - filtering routines for excluding bits of packages
+ *
+ * Copyright (C) 2007,2008 Tollef Fog Heen <tfheen@err.no>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fnmatch.h>
+
+#include <dpkg.h>
+
+#include "filters.h"
+#include "main.h"
+
+static struct filterlist *filters = NULL;
+  static struct filterlist **filtertail = &filters;
+
+static void loadfilter(const char *fn) {
+  FILE *file;
+  char linebuf[1024];
+
+  file = fopen(fn, "r");
+  if (!file) {
+    warningf(_("failed to open filter file `%.255s' for reading"), fn);
+    return;
+  }
+
+  while (fgets(linebuf, sizeof(linebuf), file)) {
+    struct filterlist *filter;
+
+    filter = m_malloc(sizeof(struct filterlist));
+    memset(filter, 0, sizeof(struct filterlist));
+
+    if (linebuf[0] == '#' || linebuf[0] == '\n') {
+      continue;
+    }
+
+    if (linebuf[strlen(linebuf) - 1] == '\n')
+      linebuf[strlen(linebuf) - 1] = '\0';
+
+    if (linebuf[0] == '+') {
+      filter->positive = 1;
+    } else if (linebuf[0] == '-') {
+      filter->positive = 0;
+    } else {
+      warningf(_("Invalid filter line: `%.255s'"), linebuf);
+      free(filter);
+      continue;
+    }
+
+    filter->filterstring = strdup(&linebuf[1]);
+    if (!filter->filterstring) {
+      ohshite(_("Error allocating memory for filter entry"));
+    }
+
+    *filtertail = filter;
+    filtertail = &filter->next;
+  }
+
+  if (ferror(file))
+    ohshite(_("read error in configuration file `%.255s'"), fn);
+
+  if (fclose(file))
+    ohshite(_("error closing configuration file `%.255s'"), fn);
+}
+
+void loadfilters(void) {
+  struct dirent *dent;
+  char *dirname = CONFIGDIR "/filters.d";
+  DIR *dir = opendir(dirname);
+  if (!dir) {
+    if (errno == ENOENT)
+      return;
+    else
+      ohshite(_("Error opening filters.d"));
+  }
+
+  while ((dent = readdir(dir)) != NULL) {
+    struct stat statbuf;
+    char *file = m_malloc(strlen(dirname) + 1 + strlen(dent->d_name) + 1);
+    sprintf(file, "%s/%s", dirname, dent->d_name);
+    if (stat(file, &statbuf) != 0) {
+      ohshite(_("Error stating file"));
+    }
+    if (S_ISREG(statbuf.st_mode)) {
+      loadfilter(file);
+    }
+    free(file);
+  }
+  closedir(dir);
+}
+
+int filter_should_skip(struct TarInfo *ti) {
+  int remove = 0;
+  if (filters) {
+    struct filterlist *f;
+
+    /* Last match wins */
+    for (f = filters; f != NULL; f = f->next) {
+      debug(dbg_eachfile, "tarobject comparing '%s' and '%s'", &ti->Name[1], f->filterstring);
+      if (fnmatch(f->filterstring, &ti->Name[1], 0) == 0) {
+	if (f->positive == 0) {
+	  remove = 1;
+	  debug(dbg_eachfile, "do_filter removing %s", ti->Name);
+	} else {
+	  remove = 0;
+	  debug(dbg_eachfile, "do_filter including %s", ti->Name);
+	}
+      }
+    }
+
+    if (remove) {
+      for (f = filters; f != NULL; f = f->next) {
+	char *pattern;
+
+	pattern = m_malloc(strlen(ti->Name) + 1);
+	strcpy(pattern, &ti->Name[1]);
+	strcat(pattern, "*");
+
+	debug(dbg_eachfile,
+	      "tarobject seeing if '%s' needs to be reincluded", &ti->Name[1]);
+	if ((f->positive == 1) &&
+	    (ti->Type == Directory) &&
+	    (fnmatch(pattern, f->filterstring, 0) == 0)) {
+	  remove = 0;
+	  debug(dbg_eachfile, "tarobject reincluding %s", ti->Name);
+	}
+      }
+    }
+  }
+  return remove;
+}
diff --git a/src/filters.h b/src/filters.h
new file mode 100644
index 0000000..f9ccaea
--- /dev/null
+++ b/src/filters.h
@@ -0,0 +1,32 @@
+/*
+ * dpkg - main program for package management
+ * filters.h - external definitions for filter handling
+ *
+ * Copyright (C) 2007,2008 Tollef Fog Heen <tfheen@err.no>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "tarfn.h"
+
+void loadfilters(void);
+int filter_should_skip(struct TarInfo *ti);
+
+struct filterlist {
+  int positive;
+  char *filterstring;
+  struct filterlist *next;
+};
+
diff --git a/src/main.c b/src/main.c
index 00b0544..0df8acc 100644
--- a/src/main.c
+++ b/src/main.c
@@ -39,6 +39,7 @@
 #include <myopt.h>
 
 #include "main.h"
+#include "filters.h"
 
 void
 printversion(void)
@@ -624,6 +625,8 @@ int main(int argc, const char *const *argv) {
   standard_startup(&ejbuf, argc, &argv, DPKG, 1, cmdinfos);
   if (!cipaction) badusage(_("need an action option"));
 
+  loadfilters();
+
   if (!f_triggers)
     f_triggers = (cipaction->arg == act_triggers && *argv) ? -1 : 1;
 
-- 
1.5.4.3


Reply to: