-
Notifications
You must be signed in to change notification settings - Fork 11
/
include-exclude.c
200 lines (168 loc) · 5.56 KB
/
include-exclude.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#include "include-exclude.h"
#include <fnmatch.h>
void IncludeExcludeAdd(HashratCtx *Ctx, int Type, const char *Item)
{
ListNode *Node;
char *Token=NULL;
const char *ptr;
static int PathRuleAdded=FALSE;
//if we get given an include with no previous excludes, then
//set CTX_EXCLUDE as the default
if (! IncludeExclude)
{
IncludeExclude=ListCreate();
}
//if the first rule added for file paths/names is 'include, then set the default to be exclude
//if the first such rule is an exlcude, then set the default to be include
if (! PathRuleAdded)
{
if (Type==CTX_INCLUDE)
{
Ctx->Flags |= CTX_EXCLUDE;
PathRuleAdded=TRUE;
}
else if (Type==CTX_EXCLUDE)
{
Ctx->Flags |= CTX_INCLUDE;
PathRuleAdded=TRUE;
}
}
ptr=GetToken(Item, ",",&Token, GETTOKEN_QUOTES);
while (ptr)
{
Node=ListAddItem(IncludeExclude, CopyStr(NULL, Token));
Node->ItemType=Type;
ptr=GetToken(ptr, ",",&Token, GETTOKEN_QUOTES);
}
Destroy(Token);
}
void IncludeExcludeLoadExcludesFromFile(const char *Path, HashratCtx *Ctx)
{
STREAM *S;
char *Tempstr=NULL;
S=STREAMOpen(Path, "r");
if (S)
{
Tempstr=STREAMReadLine(Tempstr, S);
while (Tempstr)
{
StripTrailingWhitespace(Tempstr);
IncludeExcludeAdd(Ctx, CTX_EXCLUDE, Tempstr);
Tempstr=STREAMReadLine(Tempstr, S);
}
STREAMClose(S);
}
DestroyString(Tempstr);
}
//this checks include and exclude by name. These can override each other, so you can exclude a pattern,
//but include things that match that pattern that are members of an 'include' subpattern
static int IncludeExcludeCheckFilenames(HashratCtx *Ctx, const char *Path, struct stat *FStat)
{
ListNode *Curr;
const char *mptr, *dptr;
int result=CTX_INCLUDE;
if (Ctx->Flags & CTX_EXCLUDE) result=CTX_EXCLUDE;
if (FStat && S_ISDIR(FStat->st_mode)) result=CTX_INCLUDE;
Curr=ListGetNext(IncludeExclude);
while (Curr)
{
mptr=(char *) Curr->Item;
dptr=Path;
//if match pattern doesn't start with '/' then we want to strip that off the current path
//so that we can match against it. However if the match pattern contains no '/' at all, then
//it's a file name rather than a path, in which case we should use basename on both it and
//the current path
if (*mptr != '/')
{
if (strchr(mptr,'/'))
{
if (*dptr=='/') dptr++;
}
else
{
mptr=GetBasename(mptr);
dptr=GetBasename(Path);
}
}
switch (Curr->ItemType)
{
case CTX_INCLUDE:
if (fnmatch(mptr,dptr,0)==0) result=CTX_INCLUDE;
break;
case CTX_EXCLUDE:
if (fnmatch(mptr,dptr,0)==0) result=CTX_EXCLUDE;
break;
/*
case INEX_INCLUDE_DIR:
if (strncmp(mptr,dptr,StrLen(mptr))==0) result=TRUE;
break;
case INEX_EXCLUDE_DIR:
if (strncmp(mptr,dptr,StrLen(mptr))==0) result=FALSE;
break;
*/
}
Curr=ListGetNext(Curr);
}
return(result);
}
int IncludeExcludeCheck(HashratCtx *Ctx, const char *Path, struct stat *FStat)
{
ListNode *Curr;
const char *mptr, *dptr;
int result, mult;
time_t When;
if (FStat)
{
if (Ctx->Flags & CTX_ONE_FS)
{
if (Ctx->StartingFS==0) Ctx->StartingFS=FStat->st_dev;
else if (FStat->st_dev != Ctx->StartingFS) return(CTX_ONE_FS);
}
if ((Ctx->Flags & CTX_EXES) && (! (FStat->st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))) return(CTX_EXCLUDE);
}
//'CheckIncludeExclude' checks 'normal' includes and excludes (by filename). The rest of this function
//checks properties of included files, like their mtime
result=IncludeExcludeCheckFilenames(Ctx, Path, FStat);
if (result == CTX_INCLUDE)
{
Curr=ListGetNext(IncludeExclude);
while (Curr)
{
mptr=(char *) Curr->Item;
mult=60;
switch (Curr->ItemType)
{
case CTX_MYEAR:
mult *= 365;
case CTX_MTIME:
mult *= 24 * 60;
//fall through
case CTX_MMIN:
//don't even consider mtime if we don't have a File Stat for the item, or if it's a directory
if (FStat && (! S_ISDIR(FStat->st_mode)))
{
if (*mptr=='-')
{
When=Now - atol(mptr+1) * mult;
//'since' a time will mean that the mtime for the file will be greater than that time
if (FStat->st_mtime < When) result=CTX_EXCLUDE;
}
else if (*mptr=='+')
{
When=Now - atol(mptr+1) * mult;
//'before' a time will mean that the mtime for the file will be less than that time
if (FStat->st_mtime > When) result=CTX_EXCLUDE;
}
else
{
When=Now - atol(mptr) * mult;
if ( (FStat->st_mtime < When) || (FStat->st_mtime > (When + mult)) ) result=CTX_EXCLUDE;
}
}
break;
}
Curr=ListGetNext(Curr);
}
}
return(result);
}