1 // Return 'true' if we need to exclude the file from processing as result
2 // of -x switch. If CheckInclList is true, we also check the file against
3 // the include list created with -n switch.
ExclCheck(const wchar * CheckName,bool Dir,bool CheckFullPath,bool CheckInclList)4 bool CommandData::ExclCheck(const wchar *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList)
5 {
6 if (CheckArgs(&ExclArgs,Dir,CheckName,CheckFullPath,MATCH_WILDSUBPATH))
7 return true;
8 if (!CheckInclList || InclArgs.ItemsCount()==0)
9 return false;
10 if (CheckArgs(&InclArgs,Dir,CheckName,CheckFullPath,MATCH_WILDSUBPATH))
11 return false;
12 return true;
13 }
14
15
CheckArgs(StringList * Args,bool Dir,const wchar * CheckName,bool CheckFullPath,int MatchMode)16 bool CommandData::CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,bool CheckFullPath,int MatchMode)
17 {
18 wchar *Name=ConvertPath(CheckName,NULL,0);
19 wchar FullName[NM];
20 wchar CurMask[NM];
21 *FullName=0;
22 Args->Rewind();
23 while (Args->GetString(CurMask,ASIZE(CurMask)))
24 {
25 wchar *LastMaskChar=PointToLastChar(CurMask);
26 bool DirMask=IsPathDiv(*LastMaskChar); // Mask for directories only.
27
28 if (Dir)
29 {
30 // CheckName is a directory.
31 if (DirMask)
32 {
33 // We process the directory and have the directory exclusion mask.
34 // So let's convert "mask\" to "mask" and process it normally.
35
36 *LastMaskChar=0;
37 }
38 else
39 {
40 // REMOVED, we want -npath\* to match empty folders too.
41 // If mask has wildcards in name part and does not have the trailing
42 // '\' character, we cannot use it for directories.
43
44 // if (IsWildcard(PointToName(CurMask)))
45 // continue;
46 }
47 }
48 else
49 {
50 // If we process a file inside of directory excluded by "dirmask\".
51 // we want to exclude such file too. So we convert "dirmask\" to
52 // "dirmask\*". It is important for operations other than archiving
53 // with -x. When archiving with -x, directory matched by "dirmask\"
54 // is excluded from further scanning.
55
56 if (DirMask)
57 wcsncatz(CurMask,L"*",ASIZE(CurMask));
58 }
59
60 #ifndef SFX_MODULE
61 if (CheckFullPath && IsFullPath(CurMask))
62 {
63 // We do not need to do the special "*\" processing here, because
64 // unlike the "else" part of this "if", now we convert names to full
65 // format, so they all include the path, which is matched by "*\"
66 // correctly. Moreover, removing "*\" from mask would break
67 // the comparison, because now all names have the path.
68
69 if (*FullName==0)
70 ConvertNameToFull(CheckName,FullName,ASIZE(FullName));
71 if (CmpName(CurMask,FullName,MatchMode))
72 return true;
73 }
74 else
75 #endif
76 {
77 wchar NewName[NM+2],*CurName=Name;
78
79 // Important to convert before "*\" check below, so masks like
80 // d:*\something are processed properly.
81 wchar *CmpMask=ConvertPath(CurMask,NULL,0);
82
83 if (CmpMask[0]=='*' && IsPathDiv(CmpMask[1]))
84 {
85 // We want "*\name" to match 'name' not only in subdirectories,
86 // but also in the current directory. We convert the name
87 // from 'name' to '.\name' to be matched by "*\" part even if it is
88 // in current directory.
89 NewName[0]='.';
90 NewName[1]=CPATHDIVIDER;
91 wcsncpyz(NewName+2,Name,ASIZE(NewName)-2);
92 CurName=NewName;
93 }
94
95 if (CmpName(CmpMask,CurName,MatchMode))
96 return true;
97 }
98 }
99 return false;
100 }
101
102
103
104
105 #ifndef SFX_MODULE
106 // Now this function performs only one task and only in Windows version:
107 // it skips symlinks to directories if -e1024 switch is specified.
108 // Symlinks are skipped in ScanTree class, so their entire contents
109 // is skipped too. Without this function we would check the attribute
110 // only directly before archiving, so we would skip the symlink record,
111 // but not the contents of symlinked directory.
ExclDirByAttr(uint FileAttr)112 bool CommandData::ExclDirByAttr(uint FileAttr)
113 {
114 #ifdef _WIN_ALL
115 if ((FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0 &&
116 (ExclFileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0)
117 return true;
118 #endif
119 return false;
120 }
121 #endif
122
123
124
125
126 #if !defined(SFX_MODULE)
SetTimeFilters(const wchar * Mod,bool Before,bool Age)127 void CommandData::SetTimeFilters(const wchar *Mod,bool Before,bool Age)
128 {
129 bool ModeOR=false,TimeMods=false;
130 const wchar *S=Mod;
131 // Check if any 'mca' modifiers are present, set OR mode if 'o' is present,
132 // skip modifiers and set S to beginning of time string. Be sure to check
133 // *S!=0, because termination 0 is a part of string for wcschr.
134 for (;*S!=0 && wcschr(L"MCAOmcao",*S)!=NULL;S++)
135 if (*S=='o' || *S=='O')
136 ModeOR=true;
137 else
138 TimeMods=true;
139
140 if (!TimeMods) // Assume 'm' if no modifiers are specified.
141 Mod=L"m";
142
143 // Set the specified time for every modifier. Be sure to check *Mod!=0,
144 // because termination 0 is a part of string for wcschr. This check is
145 // important when we set Mod to "m" above.
146 for (;*Mod!=0 && wcschr(L"MCAOmcao",*Mod)!=NULL;Mod++)
147 switch(toupperw(*Mod))
148 {
149 case 'M':
150 if (Before)
151 {
152 Age ? FileMtimeBefore.SetAgeText(S):FileMtimeBefore.SetIsoText(S);
153 FileMtimeBeforeOR=ModeOR;
154 }
155 else
156 {
157 Age ? FileMtimeAfter.SetAgeText(S):FileMtimeAfter.SetIsoText(S);
158 FileMtimeAfterOR=ModeOR;
159 }
160 break;
161 case 'C':
162 if (Before)
163 {
164 Age ? FileCtimeBefore.SetAgeText(S):FileCtimeBefore.SetIsoText(S);
165 FileCtimeBeforeOR=ModeOR;
166 }
167 else
168 {
169 Age ? FileCtimeAfter.SetAgeText(S):FileCtimeAfter.SetIsoText(S);
170 FileCtimeAfterOR=ModeOR;
171 }
172 break;
173 case 'A':
174 if (Before)
175 {
176 Age ? FileAtimeBefore.SetAgeText(S):FileAtimeBefore.SetIsoText(S);
177 FileAtimeBeforeOR=ModeOR;
178 }
179 else
180 {
181 Age ? FileAtimeAfter.SetAgeText(S):FileAtimeAfter.SetIsoText(S);
182 FileAtimeAfterOR=ModeOR;
183 }
184 break;
185 }
186 }
187 #endif
188
189
190 #ifndef SFX_MODULE
191 // Return 'true' if we need to exclude the file from processing.
TimeCheck(RarTime & ftm,RarTime & ftc,RarTime & fta)192 bool CommandData::TimeCheck(RarTime &ftm,RarTime &ftc,RarTime &fta)
193 {
194 bool FilterOR=false;
195
196 if (FileMtimeBefore.IsSet()) // Filter present.
197 if (ftm>=FileMtimeBefore) // Condition not matched.
198 if (FileMtimeBeforeOR)
199 FilterOR=true; // Not matched OR filter is present.
200 else
201 return true; // Exclude file in AND mode.
202 else // Condition matched.
203 if (FileMtimeBeforeOR)
204 return false; // Include file in OR mode.
205
206 if (FileMtimeAfter.IsSet()) // Filter present.
207 if (ftm<FileMtimeAfter) // Condition not matched.
208 if (FileMtimeAfterOR)
209 FilterOR=true; // Not matched OR filter is present.
210 else
211 return true; // Exclude file in AND mode.
212 else // Condition matched.
213 if (FileMtimeAfterOR)
214 return false; // Include file in OR mode.
215
216 if (FileCtimeBefore.IsSet()) // Filter present.
217 if (ftc>=FileCtimeBefore) // Condition not matched.
218 if (FileCtimeBeforeOR)
219 FilterOR=true; // Not matched OR filter is present.
220 else
221 return true; // Exclude file in AND mode.
222 else // Condition matched.
223 if (FileCtimeBeforeOR)
224 return false; // Include file in OR mode.
225
226 if (FileCtimeAfter.IsSet()) // Filter present.
227 if (ftc<FileCtimeAfter) // Condition not matched.
228 if (FileCtimeAfterOR)
229 FilterOR=true; // Not matched OR filter is present.
230 else
231 return true; // Exclude file in AND mode.
232 else // Condition matched.
233 if (FileCtimeAfterOR)
234 return false; // Include file in OR mode.
235
236 if (FileAtimeBefore.IsSet()) // Filter present.
237 if (fta>=FileAtimeBefore) // Condition not matched.
238 if (FileAtimeBeforeOR)
239 FilterOR=true; // Not matched OR filter is present.
240 else
241 return true; // Exclude file in AND mode.
242 else // Condition matched.
243 if (FileAtimeBeforeOR)
244 return false; // Include file in OR mode.
245
246 if (FileAtimeAfter.IsSet()) // Filter present.
247 if (fta<FileAtimeAfter) // Condition not matched.
248 if (FileAtimeAfterOR)
249 FilterOR=true; // Not matched OR filter is present.
250 else
251 return true; // Exclude file in AND mode.
252 else // Condition matched.
253 if (FileAtimeAfterOR)
254 return false; // Include file in OR mode.
255
256 return FilterOR; // Exclude if all OR filters are not matched.
257 }
258 #endif
259
260
261 #ifndef SFX_MODULE
262 // Return 'true' if we need to exclude the file from processing.
SizeCheck(int64 Size)263 bool CommandData::SizeCheck(int64 Size)
264 {
265 if (FileSizeLess!=INT64NDF && Size>=FileSizeLess)
266 return true;
267 if (FileSizeMore!=INT64NDF && Size<=FileSizeMore)
268 return true;
269 return false;
270 }
271 #endif
272
273
274
275
276 // Return 0 if file must not be processed or a number of matched parameter otherwise.
IsProcessFile(FileHeader & FileHead,bool * ExactMatch,int MatchType,bool Flags,wchar * MatchedArg,uint MatchedArgSize)277 int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType,
278 bool Flags,wchar *MatchedArg,uint MatchedArgSize)
279 {
280 if (MatchedArg!=NULL && MatchedArgSize>0)
281 *MatchedArg=0;
282 bool Dir=FileHead.Dir;
283 if (ExclCheck(FileHead.FileName,Dir,false,true))
284 return 0;
285 #ifndef SFX_MODULE
286 if (TimeCheck(FileHead.mtime,FileHead.ctime,FileHead.atime))
287 return 0;
288 if ((FileHead.FileAttr & ExclFileAttr)!=0 || FileHead.Dir && ExclDir)
289 return 0;
290 if (InclAttrSet && (!FileHead.Dir && (FileHead.FileAttr & InclFileAttr)==0 ||
291 FileHead.Dir && !InclDir))
292 return 0;
293 if (!Dir && SizeCheck(FileHead.UnpSize))
294 return 0;
295 #endif
296 wchar *ArgName;
297 FileArgs.Rewind();
298 for (int StringCount=1;(ArgName=FileArgs.GetString())!=NULL;StringCount++)
299 if (CmpName(ArgName,FileHead.FileName,MatchType))
300 {
301 if (ExactMatch!=NULL)
302 *ExactMatch=wcsicompc(ArgName,FileHead.FileName)==0;
303 if (MatchedArg!=NULL)
304 wcsncpyz(MatchedArg,ArgName,MatchedArgSize);
305 return StringCount;
306 }
307 return 0;
308 }
309
310
311 #if !defined(SFX_MODULE)
SetStoreTimeMode(const wchar * S)312 void CommandData::SetStoreTimeMode(const wchar *S)
313 {
314 if (*S==0 || IsDigit(*S) || *S=='-' || *S=='+')
315 {
316 // Apply -ts, -ts1, -ts-, -ts+ to all 3 times.
317 // Handle obsolete -ts[2,3,4] as ts+.
318 EXTTIME_MODE Mode=EXTTIME_MAX;
319 if (*S=='-')
320 Mode=EXTTIME_NONE;
321 if (*S=='1')
322 Mode=EXTTIME_1S;
323 xmtime=xctime=xatime=Mode;
324 S++;
325 }
326
327 while (*S!=0)
328 {
329 EXTTIME_MODE Mode=EXTTIME_MAX;
330 if (S[1]=='-')
331 Mode=EXTTIME_NONE;
332 if (S[1]=='1')
333 Mode=EXTTIME_1S;
334 switch(toupperw(*S))
335 {
336 case 'M':
337 xmtime=Mode;
338 break;
339 case 'C':
340 xctime=Mode;
341 break;
342 case 'A':
343 xatime=Mode;
344 break;
345 case 'P':
346 PreserveAtime=true;
347 break;
348 }
349 S++;
350 }
351 }
352 #endif
353