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: