From fd4fcaf350eff9a27aeaf1ec7a3616310b712f43 Mon Sep 17 00:00:00 2001 From: Tollef Fog Heen 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 | 2 + src/archives.c | 10 +++ src/filters.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++ src/filters.h | 37 ++++++++++++ src/main.c | 3 + 5 files changed, 209 insertions(+) create mode 100644 src/filters.c create mode 100644 src/filters.h diff --git a/src/Makefile.am b/src/Makefile.am index 25c3757e..fa6aeef4 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 @@ -18,6 +19,7 @@ dpkg_SOURCES = \ enquiry.c \ errors.c \ filesdb.c filesdb.h \ + filters.c filters.h \ help.c \ main.c main.h \ packages.c \ diff --git a/src/archives.c b/src/archives.c index 70fe4c5a..6789e52f 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 @@ -434,6 +435,15 @@ int tarobject(struct TarInfo *ti) { nifd->namenode->divert && nifd->namenode->divert->useinstead ? nifd->namenode->divert->useinstead->name : ""); + if (filter_should_skip(ti)) { + 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 00000000..98002a19 --- /dev/null +++ b/src/filters.c @@ -0,0 +1,157 @@ +/* + * dpkg - main program for package management + * filters.c - filtering routines for excluding bits of packages + * + * Copyright (C) 2007,2008 Tollef Fog Heen + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 00000000..540337ce --- /dev/null +++ b/src/filters.h @@ -0,0 +1,37 @@ +/* + * dpkg - main program for package management + * filters.h - external definitions for filter handling + * + * Copyright (C) 2007,2008 Tollef Fog Heen + * + * 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. + */ + +#ifndef DPKG_FILTERS_H +#define DPKG_FILTERS_H + +#include "tarfn.h" + +void loadfilters(void); +int filter_should_skip(struct TarInfo *ti); + +struct filterlist { + int positive; + char *filterstring; + struct filterlist *next; +}; + +#endif + diff --git a/src/main.c b/src/main.c index 99ac6c62..da7e7e46 100644 --- a/src/main.c +++ b/src/main.c @@ -40,6 +40,7 @@ #include #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; -- 2.39.5