1 // -*- mode: cpp; mode: fold -*-
3 // $Id: filefilter.cc,v 1.4 1999/08/05 03:22:55 jgg Exp $
4 /* ######################################################################
6 File Filter - Regular Expression maching filter
8 The idea for this was stolen shamelessly from rsync.
11 dsync-flist -e binary-alpha -i binary-all -i binary-i386 generate /tmp/listing
13 And various other incantations like that.
15 ##################################################################### */
17 // Include files /*{{{*/
19 #pragma implementation "dsync/filefilter.h"
22 #include <dsync/filefilter.h>
23 #include <dsync/error.h>
29 // FileFilter::dsFileFilter - Constructor /*{{{*/
30 // ---------------------------------------------------------------------
32 dsFileFilter::dsFileFilter() : List(0)
36 // FileFilter::~dsFileFilter - Destructor /*{{{*/
37 // ---------------------------------------------------------------------
39 dsFileFilter::~dsFileFilter()
49 // FileFilter::Test - Test a directory and file /*{{{*/
50 // ---------------------------------------------------------------------
51 /* This will return true if the named entity is included by the filter, false
52 otherwise. By default all entries are included. */
53 bool dsFileFilter::Test(const char *Directory,const char *File)
55 for (Item *I = List; I != 0; I = I->Next)
57 bool Res = I->Test(Directory,File);
61 if (I->Type == Item::Include)
64 if (I->Type == Item::Exclude)
71 // FileFilter::LoadFilter - Load the filter list from the configuration /*{{{*/
72 // ---------------------------------------------------------------------
73 /* When given the root of a configuration tree this will parse that sub-tree
74 as an ordered list of include/exclude directives. Each value in the list
75 must be prefixed with a + or a - indicating include/exclude */
76 bool dsFileFilter::LoadFilter(Configuration::Item const *Top)
81 // Advance to the end of the list
83 for (; *End != 0; End = &(*End)->Next);
90 if (Top->Value[0] == '+')
91 New->Type = Item::Include;
94 if (Top->Value[0] == '-')
95 New->Type = Item::Exclude;
99 return _error->Error("Malformed filter directive %s",Top->Tag.c_str());
103 // Strip off the +/- indicator
104 unsigned int Count = 1;
105 for (const char *I = Top->Value.c_str() + 1; I < Top->Value.c_str() + strlen(Top->Value.c_str()) &&
108 New->Pattern = string(Top->Value,Count);
112 if (New->Pattern == "*")
113 New->Flags |= Item::MatchAll;
114 if (New->Pattern.find('/') != string::npos)
115 New->Flags |= Item::MatchPath;
117 // Link it into the list
127 // FileFilter::Item::Test - Test a single item /*{{{*/
128 // ---------------------------------------------------------------------
130 bool dsFileFilter::Item::Test(const char *Directory,const char *File)
133 if ((Flags & MatchAll) == MatchAll)
136 // Append the direcotry
137 if ((Flags & MatchPath) == MatchPath)
140 if (strlen(Directory) + strlen(File) > sizeof(S))
141 return _error->Error("File field overflow");
145 return fnmatch(Pattern.c_str(),S,FNM_PATHNAME) == 0;
148 return fnmatch(Pattern.c_str(),File,FNM_PATHNAME) == 0;