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