source: trunk/dll/grep.c@ 1780

Last change on this file since 1780 was 1780, checked in by Gregg Young, 11 years ago

Fixed errors found by cppcheck. Most had the potential to cause difficult to reproduce traps. Also fixed retry code for failure to create an archive work directory and the failure of the mailto code to drop trailing >.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 46.0 KB
Line 
1
2/***********************************************************************
3
4 $Id: grep.c 1780 2014-06-28 18:05:22Z gyoung $
5
6 grep tools
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2001, 2014 Steven H. Levine
10
11 12 Feb 03 SHL InsertGrepFile: standardize EA math
12 12 Feb 03 SHL doonefile: standardize EA math
13 25 May 05 SHL Rework for ULONGLONG
14 25 May 05 SHL Rework for FillInRecordFromFFB
15 06 Jun 05 SHL Drop unused code
16 24 Oct 05 SHL dononefile: do not free EA list twice
17 22 Jul 06 SHL Use Runtime_Error
18 26 Jul 06 SHL Check more run time errors
19 19 Oct 06 SHL Correct . and .. detect
20 03 Nov 06 SHL Count thread usage
21 03 Aug 07 GKY Enlarged and made setable everywhere Findbuf (speed file loading)
22 06 Aug 07 GKY Reduce DosSleep times (ticket 148)
23 13 Aug 07 SHL Avoid pointer errors; sanitize code
24 13 Aug 07 SHL Move #pragma alloc_text to end for OpenWatcom compat
25 15 Aug 07 SHL Use FilesToGet directly
26 26 Aug 07 GKY Improved performance of FillDups
27 26 Aug 07 GKY DosSleep(1) in loops changed to (0)
28 21 Sep 07 GKY Fix trap on search that includes filenames that exceed maxpath
29 07 Feb 08 SHL Use ITIMER_DESC to control sleeps and reporting
30 29 Feb 08 GKY Use xfree where appropriate
31 29 Nov 08 GKY Remove or replace with a mutex semaphore DosEnterCriSec where appropriate.
32 07 Feb 09 GKY Allow user to turn off alert and/or error beeps in settings notebook.
33 08 Mar 09 GKY Additional strings move to String Table
34 28 Jun 09 GKY Added AddBackslashToPath() to remove repeatative code.
35 17 JAN 10 GKY Changes to get working with Watcom 1.9 Beta (1/16/10).
36 Mostly cast CHAR CONSTANT * as CHAR *.
37 29 May 10 GKY Suppress ERROR_FILENAME_EXCED_RANGE error because of problem with NTFS
38 30 May 11 GKY Fixed potential trap caused by passing a nonexistant pci to FillInRecordFromFFB
39 in DoInsertion because pci is limited to 65535 files. (nRecord is a USHORT)
40 SHL's single loop fix.
41 05 Aug 12 GKY Replace SleepIfNeeded with IdleIfNeeded to improve IU response during long searches; it
42 will switch between normal and idle priority and back.
43 05 Aug 12 GKY Always sort "Find Dups" by filename in the collector.
44 08 Feb 14 SHL Support Ignore SVN option
45 28 Jun 14 GKY Fix errors identified with CPPCheck
46
47***********************************************************************/
48
49#include <stdlib.h>
50#include <string.h>
51#include <ctype.h>
52#include <share.h>
53#include <limits.h>
54
55#define INCL_DOS
56#define INCL_DOSERRORS
57#define INCL_WIN
58#define INCL_LONGLONG
59
60#include "fm3dll.h"
61#include "fm3dll2.h" // #define's for UM_*, control id's, etc.
62#include "notebook.h" // Data declaration(s)
63#include "newview.h" // Data declarations
64#include "fm3str.h"
65#include "grep.h"
66#include "pathutil.h" // BldFullPathName
67#include "filldir.h" // FillInRecordFromFFB
68#include "makelist.h" // AddToList
69#include "errutil.h" // Dos_Error...
70#include "strutil.h" // GetPString
71#include "tmrsvcs.h" // ITIMER_DESC
72#include "common.h" // DecrThreadUsage, IncrThreadUsage
73#include "valid.h" // MakeFullName
74#include "literal.h" // wildcard
75#include "wrappers.h" // xDosFindNext
76#include "eas.h" // Free_FEAList
77#include "stristr.h" // findstring
78#include "misc.h" // PostMsg
79#include "fortify.h"
80#include "init.h" // Golbal semaphore
81#include "sortcnr.h" // SortCollectorCnr
82#include "collect.h"
83
84static VOID DoAllSubdirs(GREP *grep,
85 CHAR *searchPath,
86 BOOL recursing,
87 char **fileMasks,
88 UINT numFileMasks,
89 ITIMER_DESC *pitdSleep,
90 ITIMER_DESC *pitdReport);
91static INT DoMatchingFiles(GREP *grep,
92 CHAR *path,
93 CHAR **fileMasks,
94 UINT numFileMasks,
95 ITIMER_DESC *pitdSleep,
96 ITIMER_DESC *pitdReport);
97static BOOL DoOneFile(GREP *grep,
98 CHAR *fileName,
99 FILEFINDBUF4L *pffb,
100 ITIMER_DESC *pitdSleep,
101 ITIMER_DESC *pitdReport);
102static BOOL DoInsertion(GREP *grep,
103 ITIMER_DESC *pitdSleep,
104 ITIMER_DESC *pitdReport);
105static BOOL InsertDupe(GREP *grep, CHAR *dir, FILEFINDBUF4L *pffb);
106static VOID FillDupes(GREP *grep,
107 ITIMER_DESC *pitdSleep,
108 ITIMER_DESC *pitdReport);
109
110static VOID FreeDupes(GREP *grep);
111
112#define GREPCHARS "*?[] \\"
113
114#define isleap(year) ((((year%4)==0) && ((year%100)!=0)) || \
115 ((year%400)==0))
116
117// Data definitions
118#pragma data_seg(DATA2)
119static PSZ pszSrcFile = __FILE__;
120static INT monthdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
121
122#pragma data_seg(GLOBAL1)
123HWND hwndStatus;
124
125
126ULONG SecsSince1980(FDATE *date, FTIME *time)
127{
128 ULONG total = 0;
129 UINT x;
130
131 for (x = 1980; x < date->year + 1980; x++) {
132 if (isleap(x))
133 total += (366 * (24 * 60 * 60));
134 else
135 total += (365 * (24 * 60 * 60));
136 }
137 for (x = 1; x < date->month; x++) {
138 if (x == 2 && isleap(date->year + 1980))
139 total += (29 * (24 * 60 * 60));
140 else
141 total += ((long)monthdays[x - 1] * (24 * 60 * 60));
142 }
143 total += (((long)date->day - 1) * (24 * 60 * 60));
144 total += ((long)time->hours * (60 * 60));
145 total += ((long)time->minutes * 60);
146 total += ((long)time->twosecs * 2);
147 return total;
148}
149
150/**
151 * this function originally from C_ECHO's Snippets -- modified
152 * brute force methodology
153 */
154
155static BOOL m_match(CHAR *string, CHAR *pattern, BOOL absolute, BOOL ignore,
156 LONG len)
157{
158 // return TRUE if pattern found in string
159 register CHAR *tn = pattern;
160 register LONG len2 = 0;
161 LONG lastlen = 0;
162 CHAR lo, hi;
163
164 if (len && string && pattern) {
165 if (absolute) // no pattern matching
166 return (findstring(pattern, strlen(pattern), string, len,
167 (ignore == FALSE)) != NULL);
168
169 while (*tn && len2 < len) {
170 switch (*tn) {
171 case ' ':
172 while (*tn == ' ')
173 tn++;
174 while (len2 < len && isspace(string[len2]))
175 len2++;
176 break;
177
178 case '*':
179 while (*tn == '*' || *tn == '?')
180 tn++;
181 if (!*tn)
182 return TRUE;
183 if (ignore) {
184 while (len2 < len && string[len2] != *tn)
185 len2++;
186 }
187 else {
188 while (len2 < len && toupper(string[len2] != *tn))
189 len2++;
190 }
191 break;
192
193 case '[':
194 tn++;
195 if (!*tn)
196 return FALSE;
197 lo = *tn;
198 tn++;
199 if (*tn != '-')
200 return FALSE;
201 tn++;
202 if (!*tn)
203 return FALSE;
204 hi = *tn;
205 tn++;
206 if (*tn != ']')
207 return FALSE;
208 tn++;
209 if (ignore) {
210 if ((toupper(string[len2]) >= toupper(lo)) &&
211 (toupper(string[len2]) <= toupper(hi)))
212 len2++;
213 else {
214 tn = pattern;
215 len2 = lastlen = lastlen + 1;
216 }
217 }
218 else {
219 if ((string[len2] >= lo) && (string[len2] <= hi))
220 len2++;
221 else {
222 tn = pattern;
223 len2 = lastlen = lastlen + 1;
224 }
225 }
226 break;
227
228 case '?':
229 tn++;
230 len2++;
231 break;
232
233 case '\\':
234 tn++;
235 if (!*tn)
236 return FALSE;
237 // else intentional fallthru
238 default:
239 if (ignore) {
240 if (toupper(*tn) == toupper(string[len2])) {
241 tn++;
242 len2++;
243 }
244 else {
245 tn = pattern;
246 len2 = lastlen = lastlen + 1;
247 }
248 }
249 else {
250 if (*tn == string[len2]) {
251 tn++;
252 len2++;
253 }
254 else {
255 tn = pattern;
256 len2 = lastlen = lastlen + 1;
257 }
258 }
259 break;
260 }
261 }
262 while (*tn == '*')
263 tn++;
264
265 if (!*tn)
266 return TRUE;
267 }
268 return FALSE;
269}
270
271static BOOL match(CHAR *string, CHAR *patterns, BOOL absolute, BOOL ignore,
272 LONG len, ULONG numlines, CHAR *matched, BOOL matchall)
273{
274 BOOL ret = FALSE;
275 register CHAR *p;
276 register ULONG x = 0;
277
278 p = patterns;
279 while (!ret && *p) {
280 ret = m_match(string, p, absolute, ignore, len);
281 if (matchall && ret)
282 break;
283 if (matched && ret && x < numlines)
284 matched[x] = 1;
285 p += strlen(p); // check each pattern in 0-terminated list
286 p++;
287 x++;
288 }
289 return ret;
290}
291
292VOID GrepThread(VOID *arg)
293{
294 HAB ghab;
295 HMQ ghmq;
296 GREP grep;
297 UINT x;
298 UINT numFileMasks;
299 static CHAR *fileMasks[512]; // 06 Feb 08 SHL FIXME to not be static
300 CHAR *p, *pp, searchPath[CCHMAXPATH * 2];
301
302 ITIMER_DESC itdSleep = { 0 }; // 06 Feb 08 SHL
303 ITIMER_DESC itdReport = { 0 };
304
305 if (!arg) {
306 Runtime_Error(pszSrcFile, __LINE__, NULL);
307 return;
308 }
309
310# ifdef FORTIFY
311 Fortify_EnterScope();
312# endif
313 grep = *(GREP *)arg;
314 *grep.stopflag = 0; // reset thread-killing flag
315 DosError(FERR_DISABLEHARDERR);
316 priority_normal();
317
318 ghab = WinInitialize(0);
319 if (ghab) {
320 grep.ghab = ghab;
321 ghmq = WinCreateMsgQueue(ghab, 0);
322 if (ghmq) {
323 WinCancelShutdown(ghmq, TRUE);
324 IncrThreadUsage();
325 // DosSleep(100); //05 Aug 07 GKY 128 // 07 Feb 08 SHL
326 // hwndStatus does not exist for applet
327 WinSetWindowText(hwndStatus ? hwndStatus : grep.hwndCurFile,
328 (CHAR *) GetPString(grep.finddupes ? IDS_GREPDUPETEXT :
329 IDS_GREPSCANTEXT));
330
331 pp = grep.searchPattern;
332 while (*pp) {
333 if (!grep.absFlag) {
334 p = GREPCHARS; // see if any sense in pattern matching
335 while (*p) {
336 if (strchr(pp, *p))
337 break;
338 p++;
339 }
340 if (!*p) // nope, turn it off
341 grep.absFlag = TRUE;
342 }
343 pp = pp + strlen(pp) + 1;
344 }
345
346 grep.attrFile &= (~FILE_DIRECTORY);
347 grep.antiattr &= (~FILE_DIRECTORY);
348 if (grep.antiattr & FILE_READONLY)
349 grep.antiattr |= MUST_HAVE_READONLY;
350 if (grep.antiattr & FILE_HIDDEN)
351 grep.antiattr |= MUST_HAVE_HIDDEN;
352 if (grep.antiattr & FILE_SYSTEM)
353 grep.antiattr |= MUST_HAVE_SYSTEM;
354 if (grep.antiattr & FILE_ARCHIVED)
355 grep.antiattr |= MUST_HAVE_ARCHIVED;
356
357 grep.anyexcludes = FALSE;
358 numFileMasks = 0;
359 fileMasks[numFileMasks++] = strtok(grep.fileMasks, ";");
360
361 while ((fileMasks[numFileMasks] = strtok(NULL, ";")) != NULL && numFileMasks < 511) {
362 if (*fileMasks[numFileMasks] == '/')
363 grep.anyexcludes = TRUE;
364 numFileMasks++;
365 }
366
367 InitITimer(&itdSleep, 100); // Sleep every 100 mSec (was 500) GKY 8/11/13
368 InitITimer(&itdReport, 2000); // Report every 2 sec
369
370 // loop through search masks
371 for (x = 0; x < numFileMasks; x++) {
372
373 // Ignore exclude masks here
374 if (*fileMasks[x] == '/')
375 goto ExcludeSkip;
376
377 // Split directory pathname from mask
378 p = (char *)(fileMasks[x] + (strlen(fileMasks[x]) - 1));
379 while (*p != '\\' && *p != ':' && p != fileMasks[x])
380 --p;
381
382 if (p == fileMasks[x]) { // no path
383 strcpy(searchPath, grep.curdir);
384 strncpy(grep.fileMask, fileMasks[x], CCHMAXPATH);
385 grep.fileMask[CCHMAXPATH - 1] = 0;
386 }
387 else { // got to deal with a path
388 if (*p == ':') { // just a drive, start in root dir
389 *p = 0;
390 p++;
391 strncpy(searchPath, fileMasks[x], CCHMAXPATH - 2);
392 searchPath[CCHMAXPATH - 3] = 0;
393 strcat(searchPath, ":\\");
394 strcpy(grep.fileMask, p);
395 }
396 if (*p == '\\') {
397 // got a 'full' path
398 CHAR temp;
399
400 p++;
401 temp = *p; // Save for restore
402 *p = 0; // Chop after backslash
403 strncpy(searchPath, fileMasks[x], CCHMAXPATH);
404 searchPath[CCHMAXPATH - 1] = 0;
405 *p = temp;
406 strcpy(grep.fileMask, p);
407 }
408 if (!*grep.fileMask)
409 strcpy(grep.fileMask, "*");
410 }
411 if (*grep.stopflag)
412 break;
413 // do top level directory
414 DoMatchingFiles(&grep, searchPath, fileMasks, numFileMasks, &itdSleep, &itdReport);
415 // Recurse subdirectories if requested
416 if (grep.dirFlag)
417 DoAllSubdirs(&grep, searchPath, FALSE, fileMasks, numFileMasks, &itdSleep, &itdReport);
418
419 ExcludeSkip:
420 if (*grep.stopflag)
421 break;
422 if (WinIsWindow(grep.ghab, grep.hwndFiles))
423 DoInsertion(&grep, &itdSleep, &itdReport); // insert any remaining objects
424 } // for
425
426 if (WinIsWindow(grep.ghab, grep.hwndFiles))
427 DoInsertion(&grep, &itdSleep, &itdReport); // insert any remaining objects
428
429 if (WinIsWindow(grep.ghab, grep.hwndFiles) &&
430 grep.finddupes &&
431 !*grep.stopflag)
432 {
433 FillDupes(&grep, &itdSleep, &itdReport);
434 CollectorsortFlags = 0;
435 CollectorsortFlags |= SORT_FILENAME;
436 WinSendMsg(grep.hwndFiles, CM_SORTRECORD, MPFROMP(SortCollectorCnr),
437 MPFROMLONG(CollectorsortFlags));
438 SaySort(WinWindowFromID(WinQueryWindow(grep.hwndFiles, QW_PARENT),
439 DIR_SORT), CollectorsortFlags, FALSE);
440 }
441 if (!PostMsg(grep.hwndFiles, UM_CONTAINER_FILLED, MPVOID, MPVOID)) // tell window we're done
442 WinSendMsg(grep.hwndFiles, UM_CONTAINER_FILLED, MPVOID, MPVOID);
443 WinDestroyMsgQueue(ghmq);
444 }
445 DecrThreadUsage();
446 WinTerminate(ghab);
447 }
448 if (!ghab || !ghmq)
449 WinPostMsg(grep.hwndFiles, UM_CONTAINER_FILLED, MPVOID, MPVOID);
450 if (grep.dupehead)
451 FreeDupes(&grep);
452 if (grep.numlines && grep.matched) {
453 free(grep.matched);
454 }
455 // 07 Feb 08 SHL FIXME to free grep here when not static
456# ifdef FORTIFY
457 Fortify_LeaveScope();
458# endif
459 DosPostEventSem(CompactSem);
460}
461
462static BOOL IsExcluded(CHAR *name, CHAR **fileMasks, UINT numFileMasks)
463{
464 UINT x;
465 CHAR *n;
466
467 n = strrchr(name, '\\');
468 if (!n)
469 n = strrchr(name, ':');
470 if (n)
471 n++;
472 else
473 n = name;
474 for (x = 0; x < numFileMasks; x++) {
475 if (*fileMasks[x] == '/' &&
476 wildcard((strchr(fileMasks[x], '\\') ||
477 strchr(fileMasks[x], ':')) ? name : n, fileMasks[x] + 1, FALSE))
478 return TRUE;
479 }
480 return FALSE;
481}
482
483/**
484 * Recurse though subdirectories selecting files
485 */
486
487static VOID DoAllSubdirs(GREP *grep,
488 CHAR *searchPath,
489 BOOL recursing,
490 CHAR **fileMasks,
491 UINT numFileMasks,
492 ITIMER_DESC *pitdSleep,
493 ITIMER_DESC *pitdReport)
494{
495 FILEFINDBUF4 ffb;
496 HDIR findHandle = HDIR_CREATE;
497 ULONG ulFindCnt = 1;
498 CHAR *p = NULL;
499
500 // Append wildcard mask to directory pathname
501 AddBackslashToPath(searchPath);
502 strcat(searchPath, "*");
503 DosError(FERR_DISABLEHARDERR);
504 // Find first directory
505 if (!DosFindFirst(searchPath,
506 &findHandle,
507 (MUST_HAVE_DIRECTORY | FILE_ARCHIVED | FILE_SYSTEM |
508 FILE_HIDDEN | FILE_READONLY),
509 &ffb,
510 sizeof(ffb),
511 &ulFindCnt,
512 FIL_QUERYEASIZE))
513 {
514 // Point p at appended wildcard pattern to speed up pathname build
515 p = strrchr(searchPath, '\\');
516 if (p)
517 p++;
518 else
519 p = searchPath;
520 do { // Process each directory that matches the mask
521 int skip;
522 if (*grep->stopflag)
523 break;
524 // 2014-02-08 SHL
525 // Skip . and ..
526 skip = ffb.achName[0] == '.' &&
527 (ffb.achName[1] == 0 ||
528 (ffb.achName[1] == '.' && ffb.achName[2] == 0));
529 if (!skip && grep->ignoreSVN) {
530 // Skip version control meta data directories
531 skip = stricmp(ffb.achName, ".svn") == 0 ||
532 stricmp(ffb.achName, ".git") == 0 ||
533 stricmp(ffb.achName, ".hg") == 0 ||
534 stricmp(ffb.achName, "CVS") == 0;
535 }
536 if (!skip) {
537 strcpy(p, ffb.achName); // Build full directory pathname
538 skip = grep->anyexcludes && IsExcluded(searchPath, fileMasks, numFileMasks);
539 }
540 if (!skip) {
541 // Directory is selected
542 // 07 Feb 08 SHL
543 if (IsITimerExpired(pitdReport)) {
544 if (!hwndStatus)
545 WinSetWindowText(grep->hwndCurFile, searchPath);
546 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles) {
547 CHAR s[CCHMAXPATH + 64];
548 sprintf(s, "%s %s", GetPString(IDS_SCANNINGTEXT), searchPath);
549 WinSetWindowText(hwndStatus, s);
550 }
551 }
552 // Select files from directory
553 DoMatchingFiles(grep, searchPath, fileMasks, numFileMasks, pitdSleep, pitdReport);
554 // 07 Feb 08 SHL
555 if (IsITimerExpired(pitdReport)) {
556 priority_normal();
557 if (!hwndStatus)
558 WinSetWindowText(grep->hwndCurFile, searchPath);
559 else {
560 if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles) {
561 CHAR s[CCHMAXPATH + 64];
562 sprintf(s, "%s %s", GetPString(IDS_SCANNINGTEXT), searchPath);
563 WinSetWindowText(hwndStatus, s);
564 }
565 };
566 }
567 // Recurse
568 DoAllSubdirs(grep, searchPath, TRUE, fileMasks, numFileMasks, pitdSleep, pitdReport);
569 } // if !skip
570 ulFindCnt = 1;
571 // Get next directory
572 } while (!DosFindNext(findHandle,
573 &ffb,
574 sizeof(ffb),
575 &ulFindCnt));
576 DosFindClose(findHandle);
577 } // if at least one directory
578 if (p) // Restore orginal directory pathname
579 *p = 0;
580}
581
582/**
583 * Select files matching wildcard masks in single directory
584 */
585
586static INT DoMatchingFiles(GREP *grep,
587 CHAR *path,
588 CHAR **fileMasks,
589 UINT numFileMasks,
590 ITIMER_DESC *pitdSleep,
591 ITIMER_DESC *pitdReport)
592{
593 PFILEFINDBUF4L pffbArray;
594 PFILEFINDBUF4L pffbFile;
595 ULONG x;
596 HDIR findHandle = HDIR_CREATE;
597 ULONG ulFindCnt;
598 CHAR szFindPath[CCHMAXPATH];
599 PSZ p;
600 APIRET rc;
601 ULONG ulBufBytes = FilesToGet * sizeof(FILEFINDBUF4L);
602 static BOOL fDone;
603
604 pffbArray = xmalloc(ulBufBytes, pszSrcFile, __LINE__);
605 if (!pffbArray)
606 return 0;
607
608 BldFullPathName(szFindPath, path, grep->fileMask);
609
610 MakeFullName(szFindPath);
611
612 // Point p at wildcard mask to speed up pathname build
613 p = strrchr(szFindPath, '\\');
614 if (p)
615 p++;
616 else
617 p = szFindPath;
618
619 // Step through matching files
620 DosError(FERR_DISABLEHARDERR);
621 ulFindCnt = FilesToGet;
622 rc = xDosFindFirst(szFindPath,
623 &findHandle,
624 FILE_NORMAL | grep->attrFile | grep->antiattr,
625 pffbArray,
626 ulBufBytes,
627 &ulFindCnt,
628 FIL_QUERYEASIZEL);
629 if (!rc) {
630 do {
631 // Process each file that matches the mask
632 pffbFile = pffbArray;
633 for (x = 0; x < ulFindCnt; x++) {
634 if (*grep->stopflag)
635 break;
636 // 2014-02-08 SHL FIXME to know if really need to skip . and .. here
637 // We should only be selecting files
638 if (*pffbFile->achName != '.' ||
639 (pffbFile->achName[1] && pffbFile->achName[1] != '.')) {
640 strcpy(p, pffbFile->achName); // build full file pathname
641 if (strlen(szFindPath) > CCHMAXPATH){
642 // Complain if pathnames exceeds max
643 DosFindClose(findHandle);
644 if (!fDone) {
645 fDone = TRUE;
646 saymsg(MB_OK | MB_ICONASTERISK,
647 HWND_DESKTOP,
648 GetPString(IDS_WARNINGTEXT),
649 GetPString(IDS_LENGTHEXCEEDSMAXPATHTEXT));
650 }
651 return 1;
652 }
653
654 // 07 Feb 08 SHL
655 if (IsITimerExpired(pitdReport)) {
656 if (!hwndStatus)
657 WinSetWindowText(grep->hwndCurFile, szFindPath);
658 else {
659 if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles) {
660 CHAR s[CCHMAXPATH + 64];
661 sprintf(s, "%s %s", GetPString(IDS_SCANNINGTEXT), szFindPath);
662 WinSetWindowText(hwndStatus, s);
663 }
664 }
665 }
666
667 if (!grep->anyexcludes || !IsExcluded(szFindPath, fileMasks, numFileMasks)) {
668 // File selected
669 if (!grep->finddupes)
670 DoOneFile(grep, szFindPath, pffbFile, pitdSleep, pitdReport);
671 else if (!InsertDupe(grep, szFindPath, pffbFile)) {
672 DosFindClose(findHandle);
673 free(pffbArray);
674# ifdef FORTIFY
675 Fortify_LeaveScope();
676# endif
677 return 1;
678 }
679 }
680 }
681 if (!pffbFile->oNextEntryOffset)
682 break;
683 pffbFile = (PFILEFINDBUF4L)((PBYTE)pffbFile + pffbFile->oNextEntryOffset);
684 } // for
685 if (*grep->stopflag)
686 break;
687 IdleIfNeeded(pitdSleep, 30);
688 ulFindCnt = FilesToGet;
689 // Next file
690 rc = xDosFindNext(findHandle, pffbArray, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZEL);
691 } while (!rc);
692
693 DosFindClose(findHandle);
694 } // if at least one file
695
696 if (rc && rc != ERROR_NO_MORE_FILES) {
697 if (rc == ERROR_FILENAME_EXCED_RANGE) {
698 CHAR FileSystem[CCHMAXPATH];
699
700 CheckDrive(toupper(*szFindPath), FileSystem, NULL);
701 if (strcmp(FileSystem, NTFS))
702 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
703 GetPString(IDS_CANTFINDDIRTEXT), szFindPath);
704 }
705 else
706 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
707 GetPString(IDS_CANTFINDDIRTEXT), szFindPath);
708 }
709
710 free(pffbArray);
711# ifdef FORTIFY
712 Fortify_LeaveScope();
713# endif
714 return 0;
715}
716
717static VOID freegreplist(GREP *grep)
718{
719 UINT x;
720
721 if (grep) {
722 if (grep->insertffb) {
723 for (x = 0; grep->insertffb[x]; x++) {
724 free(grep->insertffb[x]);
725 }
726 free(grep->insertffb);
727 }
728 if (grep->dir) {
729 for (x = 0; grep->dir[x]; x++) {
730 free(grep->dir[x]);
731 }
732 free(grep->dir);
733 }
734 grep->dir = NULL;
735 grep->insertffb = NULL;
736 grep->toinsert = 0L;
737 grep->insertedbytes = 0L;
738# ifdef FORTIFY
739 Fortify_LeaveScope();
740# endif
741 }
742}
743
744/**
745 * Insert one or more records into container
746 */
747
748static BOOL DoInsertion(GREP *grep,
749 ITIMER_DESC *pitdSleep,
750 ITIMER_DESC *pitdReport)
751{
752 RECORDINSERT ri;
753 DIRCNRDATA *dcd;
754 PCNRITEM pci, pciFirst;
755 UINT x;
756 ULONG ulRecsToInsert;
757
758 if (!grep || !grep->toinsert || !grep->insertffb || !grep->dir)
759 return FALSE;
760
761 pci = NULL;
762 dcd = INSTDATA(grep->hwndFiles);
763 for (x = 0; grep->insertffb[x]; x++) {
764 if (pci == NULL) {
765 ulRecsToInsert = grep->toinsert - x < USHRT_MAX ? grep->toinsert - x : USHRT_MAX;
766 pciFirst = WinSendMsg(grep->hwndFiles, CM_ALLOCRECORD,
767 MPFROMLONG(EXTRA_RECORD_BYTES),
768 MPFROMLONG(ulRecsToInsert));
769 if (!pciFirst) {
770 Win_Error(grep->hwndFiles, grep->hwndFiles, pszSrcFile, __LINE__,
771 PCSZ_CM_ALLOCRECORD);
772 freegreplist(grep);
773 return FALSE;
774 }
775 else {
776 pci = pciFirst;
777 if (grep->sayfiles) {
778 if (!hwndStatus)
779 WinSetWindowText(grep->hwndCurFile, (CHAR *) GetPString(IDS_GREPINSERTINGTEXT));
780 else {
781 if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
782 WinSetWindowText(hwndStatus, (CHAR *) GetPString(IDS_GREPINSERTINGTEXT));
783 }
784 }
785 }
786 }
787 FillInRecordFromFFB(grep->hwndFiles,
788 pci, grep->dir[x], grep->insertffb[x], FALSE, dcd);
789 pci = (PCNRITEM) pci->rc.preccNextRecord;
790 //SleepIfNeeded(pitdSleep, 1);
791 if (pci == NULL && ulRecsToInsert) {
792 memset(&ri, 0, sizeof(RECORDINSERT));
793 ri.cb = sizeof(RECORDINSERT);
794 ri.pRecordOrder = (PRECORDCORE) CMA_END;
795 ri.pRecordParent = (PRECORDCORE) NULL;
796 ri.zOrder = (USHORT) CMA_TOP;
797 ri.cRecordsInsert = ulRecsToInsert;
798 ri.fInvalidateRecord = TRUE;
799 WinSendMsg(grep->hwndFiles,
800 CM_INSERTRECORD, MPFROMP(pciFirst), MPFROMP(&ri));
801 if (dcd) {
802 DosRequestMutexSem(hmtxFM2Globals, SEM_INDEFINITE_WAIT);
803 dcd->ullTotalBytes += grep->insertedbytes;
804 DosReleaseMutexSem(hmtxFM2Globals);
805 }
806 pciFirst = NULL;
807 }
808 SleepIfNeeded(pitdSleep, 1);
809 }//for
810 // if (grep->toinsert == FilesToGet) // 07 Feb 08 SHL
811 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
812 freegreplist(grep);
813 PostMsg(grep->hwndFiles, UM_RESCAN, MPVOID, MPVOID);
814 return TRUE;
815}
816
817/**
818 * Insert file ffb and directory name into lists
819 */
820
821static BOOL InsertGrepFile(GREP *grep,
822 CHAR *pszFileName,
823 PFILEFINDBUF4L pffb,
824 ITIMER_DESC *pitdSleep,
825 ITIMER_DESC *pitdReport)
826{
827 PSZ p;
828 CHAR szDirectory[CCHMAXPATH];
829
830 if (!WinIsWindow(grep->ghab, grep->hwndFiles)) {
831 // Window closed - clean up and go away
832 freegreplist(grep);
833 }
834 else {
835 grep->numfiles++;
836 strcpy(szDirectory, pszFileName);
837 p = strrchr(szDirectory, '\\');
838
839 if (p) {
840 // Got directory
841 if (p < szDirectory + 4)
842 p++; // Include root backslash
843 *p = 0;
844
845 if (!grep->insertffb) {
846 // Allocate 1 extra for end marker?
847 grep->insertffb = xmallocz(sizeof(PFILEFINDBUF4L) * (FilesToGet + 1),
848 pszSrcFile, __LINE__);
849 if (!grep->insertffb)
850 return FALSE;
851 grep->dir = xmallocz(sizeof(CHAR *) * (FilesToGet + 1),
852 pszSrcFile, __LINE__);
853 if (!grep->dir) {
854 free(grep->insertffb);
855# ifdef FORTIFY
856 Fortify_LeaveScope();
857# endif
858 return FALSE;
859 }
860 }
861
862 grep->insertffb[grep->toinsert] =
863 xmalloc(sizeof(FILEFINDBUF4L), pszSrcFile, __LINE__);
864 if (!grep->insertffb[grep->toinsert])
865 return FALSE;
866 memcpy(grep->insertffb[grep->toinsert], pffb, sizeof(FILEFINDBUF4L));
867
868 grep->dir[grep->toinsert] = xstrdup(szDirectory, pszSrcFile, __LINE__);
869 if (!grep->dir) {
870 free(grep->insertffb[grep->toinsert]);
871# ifdef FORTIFY
872 Fortify_LeaveScope();
873# endif
874 return FALSE;
875 }
876
877 grep->insertedbytes += pffb->cbFile + CBLIST_TO_EASIZE(pffb->cbList);
878 grep->toinsert++;
879 // 07 Oct 09 SHL honor sync updates
880 if (grep->toinsert == FilesToGet || fSyncUpdates)
881 return DoInsertion(grep, pitdSleep, pitdReport);
882 return TRUE;
883 }
884 }
885 return FALSE;
886}
887
888/**
889 * Check file matches search criteria
890 */
891
892static BOOL DoOneFile(GREP *grep,
893 CHAR *pszFileName,
894 FILEFINDBUF4L *pffb,
895 ITIMER_DESC *pitdSleep,
896 ITIMER_DESC *pitdReport)
897{
898 // process a single file
899 CHAR *input;
900 FILE *inputFile;
901 ULONG pos;
902 BOOL ret = FALSE, strmatch = FALSE;
903
904 grep->fileCount++;
905 if (grep->sayfiles) {
906 if (!hwndStatus)
907 WinSetWindowText(grep->hwndCurFile, pszFileName);
908 else {
909 if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
910 WinSetWindowText(hwndStatus, pszFileName);
911 }
912 }
913
914 if (grep->greaterthan || grep->lessthan) {
915
916 BOOL keep = TRUE;
917 ULONG adjsize;
918
919 adjsize = pffb->cbFile + (grep->searchEAs ? CBLIST_TO_EASIZE(pffb->cbList) : 0);
920 if (grep->greaterthan) {
921 if (adjsize < grep->greaterthan)
922 keep = FALSE;
923 }
924 if (keep && grep->lessthan) {
925 if (adjsize > grep->lessthan)
926 keep = FALSE;
927 }
928 if (!keep)
929 return ret;
930 }
931
932 if (grep->newerthan || grep->olderthan) {
933
934 BOOL keep = TRUE;
935 ULONG numsecs;
936
937 numsecs = SecsSince1980(&pffb->fdateLastWrite, &pffb->ftimeLastWrite);
938 if (grep->newerthan) {
939 if (numsecs < grep->newerthan)
940 keep = FALSE;
941 }
942 if (keep && grep->olderthan) {
943 if (numsecs > grep->olderthan)
944 keep = FALSE;
945 }
946 if (!keep)
947 return ret;
948 }
949
950 if ((!grep->searchEAs && !grep->searchFiles) || !*grep->searchPattern) // just a find
951 return InsertGrepFile(grep, pszFileName, pffb, pitdSleep, pitdReport);
952
953 if (grep->searchEAs) {
954
955 HOLDFEA *head, *info;
956 USHORT type, len;
957 BOOL alltext;
958 CHAR *data, temp;
959
960 head = GetFileEAs(pszFileName, FALSE, TRUE);
961 if (head) {
962 info = head;
963 while (info && !strmatch) {
964 alltext = TRUE;
965 switch (*(USHORT *)info->value) {
966 case EAT_ASCII:
967 if (match(info->value + (sizeof(USHORT) * 2),
968 grep->searchPattern, grep->absFlag,
969 grep->caseFlag == FALSE,
970 info->cbValue - (sizeof(USHORT) * 2),
971 grep->numlines,
972 grep->matched,
973 !grep->findifany)) {
974 strmatch = TRUE;
975 }
976 break;
977 case EAT_MVST:
978 type = *(USHORT *)(info->value + (sizeof(USHORT) * 3));
979 if (type == EAT_ASCII) {
980 data = info->value + (sizeof(USHORT) * 4);
981 len = *(USHORT *) data;
982 data += sizeof(USHORT);
983 while ((data - info->value) + len <= info->cbValue) {
984 temp = *(data + len);
985 *(data + len) = 0;
986 if (match(data,
987 grep->searchPattern,
988 grep->absFlag,
989 (grep->caseFlag == FALSE),
990 len,
991 grep->numlines, grep->matched, !grep->findifany)) {
992 strmatch = TRUE;
993 break;
994 }
995 data += len;
996 if (data - info->value >= info->cbValue)
997 break;
998 *data = temp;
999 len = *(USHORT *) data;
1000 data += sizeof(USHORT);
1001 }
1002 }
1003 break;
1004 case EAT_MVMT:
1005 data = info->value + (sizeof(USHORT) * 3);
1006 type = *(USHORT *) data;
1007 data += sizeof(USHORT);
1008 len = *(USHORT *) data;
1009 data += sizeof(USHORT);
1010 while ((data - info->value) - len <= info->cbValue) {
1011 if (type != EAT_ASCII) {
1012 alltext = FALSE;
1013 break;
1014 }
1015 data += len;
1016 if (data - info->value >= info->cbValue)
1017 break;
1018 type = *(USHORT *) data;
1019 data += sizeof(USHORT);
1020 len = *(USHORT *) data;
1021 data += sizeof(USHORT);
1022 }
1023 if (alltext) {
1024 data = info->value + (sizeof(USHORT) * 3);
1025 type = *(USHORT *) data;
1026 data += sizeof(USHORT);
1027 len = *(USHORT *) data;
1028 data += sizeof(USHORT);
1029 while ((data - info->value) - len <= info->cbValue) {
1030 temp = *(data + len);
1031 *(data + len) = 0;
1032 if (match(data,
1033 grep->searchPattern,
1034 grep->absFlag,
1035 (grep->caseFlag == FALSE),
1036 len,
1037 grep->numlines, grep->matched, !grep->findifany)) {
1038 strmatch = TRUE;
1039 break;
1040 }
1041 data += len;
1042 *data = temp;
1043 if (data - info->value >= info->cbValue)
1044 break;
1045 type = *(USHORT *) data;
1046 data += sizeof(USHORT);
1047 len = *(USHORT *) data;
1048 data += sizeof(USHORT);
1049 }
1050 }
1051 break;
1052 default:
1053 break;
1054 }
1055 info = info->next;
1056 } // while
1057 Free_FEAList(head);
1058 // DosSleep(1); // 07 Feb 08 SHL
1059 }
1060 }
1061
1062 if (grep->searchFiles) {
1063 input = xmalloc(65537, pszSrcFile, __LINE__);
1064 if (input) {
1065 LONG len;
1066 CHAR *moderb = "rb";
1067
1068 inputFile = xfsopen(pszFileName, moderb, SH_DENYNO, pszSrcFile, __LINE__, TRUE);
1069 if (inputFile) {
1070 pos = ftell(inputFile);
1071 while (!feof(inputFile)) {
1072 if (pos)
1073 fseek(inputFile, pos - 1024, SEEK_SET);
1074 len = fread(input, 1, 65536, inputFile);
1075 if (len >= 0) {
1076 if (*grep->stopflag)
1077 break;
1078 if (match(input,
1079 grep->searchPattern,
1080 grep->absFlag,
1081 (grep->caseFlag == FALSE),
1082 len, grep->numlines, grep->matched, !grep->findifany)) {
1083 strmatch = TRUE;
1084 break;
1085 }
1086 }
1087 else
1088 break;
1089 }
1090 fclose(inputFile);
1091 }
1092 free(input);
1093# ifdef FORTIFY
1094 Fortify_LeaveScope();
1095# endif
1096 // DosSleep(1); // 07 Feb 08 SHL
1097 }
1098 } // if
1099
1100 if (strmatch)
1101 ret = InsertGrepFile(grep, pszFileName, pffb, pitdSleep, pitdReport);
1102 return ret;
1103}
1104
1105static LONG cr3tab[] = { // CRC polynomial 0xEDB88320
1106
1107 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
1108 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
1109 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
1110 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
1111 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
1112 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
1113 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
1114 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
1115 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
1116 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
1117 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
1118 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
1119 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
1120 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
1121 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1122 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
1123 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
1124 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
1125 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
1126 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
1127 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
1128 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
1129 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
1130 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
1131 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
1132 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
1133 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
1134 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
1135 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
1136 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1137 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
1138 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
1139 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
1140 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
1141 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
1142 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
1143 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
1144 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
1145 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
1146 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
1147 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
1148 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
1149 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
1150 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
1151 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1152 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
1153 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
1154 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
1155 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
1156 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
1157 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
1158 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
1159 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
1160 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
1161 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
1162 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
1163 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
1164 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
1165 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
1166 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1167 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
1168 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
1169 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
1170 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
1171};
1172
1173LONG CRCBlock(register CHAR *str, register INT blklen, register LONG crc)
1174{
1175 while (blklen--) {
1176 crc =
1177 cr3tab[((INT) crc ^ *str) & 0xff] ^ (((ULONG) crc >> 8) & 0x00FFFFFF);
1178 str++;
1179 }
1180 return crc;
1181}
1182
1183LONG CRCFile(CHAR *pszFileName, INT *error)
1184{
1185 LONG CRC = -1L, len;
1186 FILE *fp;
1187 CHAR *buffer;
1188 CHAR *moderb = "rb";
1189
1190 *error = 0;
1191 buffer = xmalloc(65535, pszSrcFile, __LINE__);
1192 if (!buffer)
1193 *error = -1;
1194 else {
1195 fp = xfsopen(pszFileName, moderb, SH_DENYNO, pszSrcFile, __LINE__, TRUE);
1196 if (!fp)
1197 *error = -2;
1198 else {
1199 while (!feof(fp)) {
1200 len = fread(buffer, 1, 65535, fp);
1201 if (len && len < 65536L)
1202 CRC = CRCBlock(buffer, len, CRC);
1203 else
1204 break;
1205 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
1206 }
1207 fclose(fp);
1208 // DosSleep(1); // 07 Feb 08 SHL
1209 }
1210 free(buffer);
1211# ifdef FORTIFY
1212 Fortify_LeaveScope();
1213# endif
1214 }
1215 return CRC;
1216}
1217
1218static VOID FreeDupes(GREP *grep)
1219{
1220 DUPES *i, *next;
1221
1222 i = grep->dupehead;
1223 while (i) {
1224 next = i->next;
1225 if (i->name) {
1226 free(i->name);
1227 }
1228 free(i);
1229 i = next;
1230 }
1231 grep->dupehead = grep->dupelast = NULL;
1232 xfree(grep->dupenames, pszSrcFile, __LINE__);
1233 xfree(grep->dupesizes, pszSrcFile, __LINE__);
1234 grep->dupesizes = grep->dupenames = NULL;
1235# ifdef FORTIFY
1236 Fortify_LeaveScope();
1237# endif
1238}
1239
1240INT comparenamesq(const VOID *v1, const VOID *v2)
1241{
1242 DUPES *d1 = *(DUPES **) v1;
1243 DUPES *d2 = *(DUPES **) v2;
1244 CHAR *p1, *p2;
1245
1246 p1 = strrchr(d1->name, '\\');
1247 if (p1)
1248 p1++;
1249 else
1250 p1 = d1->name;
1251 p2 = strrchr(d2->name, '\\');
1252 if (p2)
1253 p2++;
1254 else
1255 p2 = d2->name;
1256 return stricmp(p1, p2);
1257}
1258
1259INT comparenamesqe(const VOID *v1, const VOID *v2)
1260{
1261 DUPES *d1 = *(DUPES **) v1;
1262 DUPES *d2 = *(DUPES **) v2;
1263 CHAR *p1, *p2, *p1e, *p2e, e1, e2;
1264 INT ret;
1265
1266 p1 = strrchr(d1->name, '\\');
1267 if (p1)
1268 p1++;
1269 else
1270 p1 = d1->name;
1271 p1e = strrchr(p1, '.');
1272 if (p1e) {
1273 e1 = *p1e;
1274 *p1e = 0;
1275 }
1276 p2 = strrchr(d2->name, '\\');
1277 if (p2)
1278 p2++;
1279 else
1280 p2 = d2->name;
1281 p2e = strrchr(p2, '.');
1282 if (p2e) {
1283 e2 = *p2e;
1284 *p2e = 0;
1285 }
1286 ret = stricmp(p1, p2);
1287 if (p1e)
1288 *p1e = e1;
1289 if (p2e)
1290 *p2e = e2;
1291 return ret;
1292}
1293
1294INT comparesizesq(const void *v1, const void *v2)
1295{
1296 DUPES *d1 = *(DUPES **) v1;
1297 DUPES *d2 = *(DUPES **) v2;
1298
1299 return (d1->size > d2->size) ? 1 : (d1->size == d2->size) ? 0 : -1;
1300}
1301
1302INT comparenamesb(const void *v1, const void *v2)
1303{
1304 DUPES *d1 = (DUPES *) v1;
1305 DUPES *d2 = *(DUPES **) v2;
1306 CHAR *p1, *p2;
1307
1308 p1 = strrchr(d1->name, '\\');
1309 if (p1)
1310 p1++;
1311 else
1312 p1 = d1->name;
1313 p2 = strrchr(d2->name, '\\');
1314 if (p2)
1315 p2++;
1316 else
1317 p2 = d2->name;
1318 return stricmp(p1, p2);
1319}
1320
1321INT comparenamesbe(const VOID *v1, const VOID *v2)
1322{
1323 DUPES *d1 = (DUPES *) v1;
1324 DUPES *d2 = *(DUPES **) v2;
1325 CHAR *p1, *p2, *p1e, *p2e, e1, e2;
1326 INT ret;
1327
1328 p1 = strrchr(d1->name, '\\');
1329 if (p1)
1330 p1++;
1331 else
1332 p1 = d1->name;
1333 p1e = strrchr(p1, '.');
1334 if (p1e) {
1335 e1 = *p1e;
1336 *p1e = 0;
1337 }
1338 p2 = strrchr(d2->name, '\\');
1339 if (p2)
1340 p2++;
1341 else
1342 p2 = d2->name;
1343 p2e = strrchr(p2, '.');
1344 if (p2e) {
1345 e2 = *p2e;
1346 *p2e = 0;
1347 }
1348 ret = stricmp(p1, p2);
1349 if (p1e)
1350 *p1e = e1;
1351 if (p2e)
1352 *p2e = e2;
1353 return ret;
1354}
1355
1356INT comparesizesb(const VOID *v1, const VOID *v2)
1357{
1358 DUPES *d1 = (DUPES *) v1;
1359 DUPES *d2 = *(DUPES **) v2;
1360
1361 return (d1->size > d2->size) ? 1 : (d1->size == d2->size) ? 0 : -1;
1362}
1363
1364static VOID FillDupes(GREP *grep,
1365 ITIMER_DESC *pitdSleep,
1366 ITIMER_DESC *pitdReport)
1367{
1368 DUPES *c, *i, **r;
1369 register CHAR *pc, *pi;
1370 CHAR **list = NULL;
1371 UINT numfiles = 0, numalloced = 0;
1372 INT error;
1373 ULONG x;
1374 ULONG y;
1375 // ULONG cntr = 1000; // 09 Feb 08 SHL
1376
1377 // if (grep->CRCdupes) // 09 Feb 08 SHL
1378 // cntr = 100; // 09 Feb 08 SHL
1379 x = 0;
1380 for (i = grep->dupehead; i; i = i->next)
1381 x++; // Count
1382
1383 if (x) {
1384 if (!hwndStatus)
1385 WinSetWindowText(grep->hwndCurFile, (CHAR *) GetPString(IDS_GREPDUPESORTINGTEXT));
1386 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1387 WinSetWindowText(hwndStatus, (CHAR *) GetPString(IDS_GREPDUPESORTINGTEXT));
1388 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
1389 grep->dupenames = xmalloc(sizeof(DUPES *) * (x + 1), pszSrcFile, __LINE__);
1390 if (!grep->nosizedupes)
1391 grep->dupesizes = xmalloc(sizeof(DUPES *) * (x + 1), pszSrcFile, __LINE__);
1392 if (grep->dupenames && (grep->nosizedupes || grep->dupesizes)) {
1393 y = 0;
1394 for (i = grep->dupehead; i; i = i->next) {
1395 grep->dupenames[y] = i;
1396 if (!grep->nosizedupes)
1397 grep->dupesizes[y] = i;
1398 y++;
1399 }
1400 grep->dupenames[y] = NULL; // Mark end
1401 if (!grep->nosizedupes)
1402 grep->dupesizes[y] = NULL;
1403
1404 InitITimer(pitdSleep, 0); // Reset rate estimator
1405 SleepIfNeeded(pitdSleep, 1);
1406 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
1407
1408 qsort(grep->dupenames,
1409 x,
1410 sizeof(DUPES *),
1411 grep->ignoreextdupes ? comparenamesqe : comparenamesq);
1412 SleepIfNeeded(pitdSleep, 1);
1413 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
1414 if (!grep->nosizedupes) {
1415 qsort(grep->dupesizes, x, sizeof(DUPES *), comparesizesq);
1416 SleepIfNeeded(pitdSleep, 1);
1417 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
1418 }
1419
1420 if (!hwndStatus)
1421 WinSetWindowText(grep->hwndCurFile, (CHAR *) GetPString(IDS_GREPDUPECOMPARINGTEXT));
1422 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1423 WinSetWindowText(hwndStatus, (CHAR *) GetPString(IDS_GREPDUPECOMPARINGTEXT));
1424
1425 InitITimer(pitdSleep, 0); // Reset rate estimator
1426 i = grep->dupehead;
1427 y = 0;
1428 while (i) {
1429 if (*grep->stopflag)
1430 break;
1431 SleepIfNeeded(pitdSleep, 1); // 07 Feb 08 SHL
1432 if (!(i->flags & GF_SKIPME)) {
1433 r = (DUPES **) bsearch(i, grep->dupenames, x, sizeof(DUPES *),
1434 ((grep->ignoreextdupes) ? comparenamesbe :
1435 comparenamesb));
1436 if (r) {
1437 while (r > grep->dupenames && ((grep->ignoreextdupes) ?
1438 !comparenamesqe((r - 1), &i) :
1439 !comparenamesq((r - 1), &i)))
1440 r--;
1441 while (*r && ((grep->ignoreextdupes) ?
1442 !comparenamesqe(r, &i) : !comparenamesq(r, &i))) {
1443 if (*r == i || ((*r)->flags & (GF_INSERTED | GF_SKIPME))) {
1444 r++;
1445 continue;
1446 }
1447 if (grep->CRCdupes) {
1448 if ((*r)->CRC == -1L) {
1449 (*r)->CRC = CRCFile((*r)->name, &error);
1450 if (error)
1451 (*r)->CRC = -1L;
1452 else if ((*r)->CRC == -1L)
1453 (*r)->CRC = 0L;
1454 }
1455 if (i->CRC == -1L) {
1456 i->CRC = CRCFile(i->name, &error);
1457 if (error)
1458 i->CRC = -1L;
1459 else if (i->CRC == -1L)
1460 i->CRC = 0L;
1461 }
1462 if (((*r)->size != i->size) || ((*r)->CRC != -1L &&
1463 i->CRC != -1L
1464 && (*r)->CRC != i->CRC)) {
1465 r++;
1466 continue;
1467 }
1468 }
1469 if (!AddToList((*r)->name, &list, &numfiles, &numalloced)) {
1470 (*r)->flags |= GF_INSERTED;
1471 if (grep->sayfiles) {
1472 if (!hwndStatus)
1473 WinSetWindowText(grep->hwndFiles, (*r)->name);
1474 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1475 WinSetWindowText(hwndStatus, (*r)->name);
1476 }
1477 if ((*r)->size == i->size &&
1478 (i->date.year == (*r)->date.year &&
1479 i->date.month == (*r)->date.month &&
1480 i->date.day == (*r)->date.day &&
1481 i->time.hours == (*r)->time.hours &&
1482 i->time.minutes == (*r)->time.minutes &&
1483 i->time.twosecs == (*r)->time.twosecs))
1484 (*r)->flags |= GF_SKIPME;
1485 }
1486 if (!(i->flags & (GF_INSERTED | GF_SKIPME))) {
1487 if (!AddToList(i->name, &list, &numfiles, &numalloced)) {
1488 i->flags |= GF_INSERTED;
1489 if ((*r)->flags & GF_SKIPME)
1490 i->flags |= GF_SKIPME;
1491 }
1492 }
1493 r++;
1494 }
1495 }
1496 if (!grep->nosizedupes) {
1497 r = (DUPES **) bsearch(i,
1498 grep->dupesizes,
1499 x, sizeof(DUPES *), comparesizesb);
1500 if (r) {
1501 while (r > grep->dupesizes && !comparesizesq((r - 1), &i))
1502 r--;
1503 while (*r && !comparesizesq(r, &i)) {
1504 if (*r == i || ((*r)->flags & (GF_INSERTED | GF_SKIPME)) ||
1505 (i->date.year != (*r)->date.year ||
1506 i->date.month != (*r)->date.month ||
1507 i->date.day != (*r)->date.day ||
1508 i->time.hours != (*r)->time.hours ||
1509 i->time.minutes != (*r)->time.minutes ||
1510 i->time.twosecs != (*r)->time.twosecs)) {
1511 r++;
1512 continue;
1513 }
1514 if (grep->CRCdupes) {
1515 if ((*r)->CRC == -1L) {
1516 (*r)->CRC = CRCFile((*r)->name, &error);
1517 if (error)
1518 (*r)->CRC = -1L;
1519 else if ((*r)->CRC == -1L)
1520 (*r)->CRC = 0L;
1521 }
1522 if (i->CRC == -1L) {
1523 i->CRC = CRCFile(i->name, &error);
1524 if (error)
1525 i->CRC = -1L;
1526 else if (i->CRC == -1L)
1527 i->CRC = 0L;
1528 }
1529 if ((*r)->CRC != -1L && i->CRC != -1L &&
1530 (*r)->CRC != i->CRC) {
1531 *r += 1;
1532 continue;
1533 }
1534 }
1535 if (!AddToList((*r)->name, &list, &numfiles, &numalloced)) {
1536 if (grep->sayfiles) {
1537 if (!hwndStatus)
1538 WinSetWindowText(grep->hwndCurFile, (*r)->name);
1539 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1540 WinSetWindowText(hwndStatus, (*r)->name);
1541 }
1542 (*r)->flags |= GF_INSERTED;
1543 if (((grep->ignoreextdupes) ?
1544 comparenamesqe(r, &i) : comparenamesq(r, &i)))
1545 (*r)->flags |= GF_SKIPME;
1546 }
1547 if (!(i->flags & (GF_INSERTED | GF_SKIPME))) {
1548 if (!AddToList(i->name, &list, &numfiles, &numalloced)) {
1549 i->flags |= GF_INSERTED;
1550 if ((*r)->flags & GF_SKIPME)
1551 i->flags |= GF_SKIPME;
1552 }
1553 }
1554 r++;
1555 }
1556 }
1557 }
1558 }
1559 i = i->next;
1560 y++;
1561 // 08 Feb 08 SHL
1562 if (IsITimerExpired(pitdReport)) {
1563 CHAR s[44];
1564 sprintf(s, GetPString(IDS_GREPDUPECHECKPROGTEXT), y, grep->numfiles);
1565 if (!hwndStatus)
1566 WinSetWindowText(grep->hwndCurFile, s);
1567 else {
1568 if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1569 WinSetWindowText(hwndStatus, s);
1570 }
1571 }
1572 } // while
1573 }
1574 else {
1575 // Insufficient memory - fall back to slow method - FIXME to saymsg?
1576 if (!fErrorBeepOff)
1577 DosBeep(50, 100);
1578 if (!hwndStatus)
1579 WinSetWindowText(grep->hwndCurFile, (CHAR *) GetPString(IDS_GREPDUPECOMPARINGTEXT));
1580 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1581 WinSetWindowText(hwndStatus, (CHAR *) GetPString(IDS_GREPDUPECOMPARINGTEXT));
1582 x = y = 0;
1583 xfree(grep->dupenames, pszSrcFile, __LINE__);
1584 grep->dupenames = NULL;
1585 xfree(grep->dupesizes, pszSrcFile, __LINE__);
1586 grep->dupesizes = NULL;
1587# ifdef FORTIFY
1588 Fortify_LeaveScope();
1589# endif
1590
1591 InitITimer(pitdSleep, 0); // Reset rate estimator
1592 i = grep->dupehead;
1593 while (i) {
1594 if (*grep->stopflag)
1595 break;
1596 SleepIfNeeded(pitdSleep, 1);
1597 if (!(i->flags & GF_SKIPME)) {
1598 if (IsITimerExpired(pitdReport)) {
1599 // if (!(y % cntr)) { }
1600 CHAR s[44];
1601 sprintf(s, GetPString(IDS_GREPDUPECHECKPROGTEXT), y, grep->numfiles);
1602 if (!hwndStatus)
1603 WinSetWindowText(grep->hwndCurFile, s);
1604 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1605 WinSetWindowText(hwndStatus, s);
1606 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
1607 }
1608 y++;
1609 pi = strrchr(i->name, '\\');
1610 if (pi)
1611 pi++;
1612 else
1613 pi = i->name;
1614 c = grep->dupehead;
1615 while (c) {
1616 if (*grep->stopflag)
1617 break;
1618 if (c != i && !(c->flags & (GF_INSERTED | GF_SKIPME))) {
1619 x++;
1620 pc = strrchr(c->name, '\\');
1621 if (pc)
1622 pc++;
1623 else
1624 pc = c->name;
1625 if ((!grep->nosizedupes && i->size == c->size && i->date.year == c->date.year && i->date.month == c->date.month && i->date.day == c->date.day && i->time.hours == c->time.hours && i->time.minutes == c->time.minutes && i->time.twosecs == c->time.twosecs) || !stricmp(pc, pi)) { // potential dupe
1626 if (grep->CRCdupes) {
1627 if (grep->CRCdupes) {
1628 if (c->CRC == -1L) {
1629 c->CRC = CRCFile(c->name, &error);
1630 if (error)
1631 c->CRC = -1L;
1632 else if (c->CRC == -1L)
1633 c->CRC = 0L;
1634 }
1635 if (i->CRC == -1L) {
1636 i->CRC = CRCFile(i->name, &error);
1637 if (error)
1638 i->CRC = -1L;
1639 else if (i->CRC == -1L)
1640 i->CRC = 0L;
1641 }
1642 if ((c->size != i->size) || (c->CRC != -1L &&
1643 i->CRC != -1L
1644 && c->CRC != i->CRC)) {
1645 c = c->next;
1646 continue;
1647 }
1648 }
1649 }
1650 if (AddToList(c->name, &list, &numfiles, &numalloced))
1651 goto BreakOut; // Failed
1652 if (!(i->flags & GF_INSERTED)) {
1653 if (AddToList(i->name, &list, &numfiles, &numalloced))
1654 goto BreakOut; // Failed
1655 }
1656 if (grep->sayfiles) {
1657 if (!hwndStatus)
1658 WinSetWindowText(grep->hwndCurFile, pc);
1659 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1660 WinSetWindowText(hwndStatus, pc);
1661 }
1662 c->flags |= GF_INSERTED;
1663 i->flags |= GF_INSERTED;
1664 if (!stricmp(pc, pi)) {
1665 c->flags |= GF_SKIPME;
1666 i->flags |= GF_SKIPME;
1667 }
1668 }
1669 // else if (!(x % 100)) // 07 Feb 08 SHL
1670 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
1671 }
1672 c = c->next;
1673 }
1674 }
1675 i = i->next;
1676 } // while
1677 }
1678 }
1679BreakOut:
1680 FreeDupes(grep);
1681 if (numfiles && list) {
1682 if (!PostMsg(grep->hwndFiles,
1683 WM_COMMAND,
1684 MPFROM2SHORT(IDM_COLLECTOR, 0),
1685 MPFROMP(list)))
1686 FreeList(list);
1687 }
1688 else
1689 DosPostEventSem(CompactSem);
1690}
1691
1692static BOOL InsertDupe(GREP *grep, CHAR *dir, FILEFINDBUF4L *pffb)
1693{
1694 DUPES *info;
1695
1696 if (*dir) {
1697 info = xmallocz(sizeof(DUPES), pszSrcFile, __LINE__);
1698 if (!info)
1699 return FALSE;
1700
1701 info->name = xstrdup(dir, pszSrcFile, __LINE__);
1702 if (!info->name) {
1703 free(info);
1704# ifdef FORTIFY
1705 Fortify_LeaveScope();
1706# endif
1707 return FALSE;
1708 }
1709
1710 info->size = pffb->cbFile;
1711 info->date = pffb->fdateLastWrite;
1712 info->time = pffb->ftimeLastWrite;
1713 info->CRC = -1L;
1714 grep->numfiles++;
1715 if (!grep->dupehead)
1716 grep->dupehead = info;
1717 if (grep->dupelast)
1718 grep->dupelast->next = info;
1719 grep->dupelast = info;
1720 info->next = NULL;
1721 }
1722 return TRUE;
1723}
1724
1725#pragma alloc_text(GREP,InsertGrepFile,DoOneFile,DoInsertion,freegreplist)
1726#pragma alloc_text(GREP,SecsSince1980,match,mmatch,GrepThread)
1727#pragma alloc_text(GREP,DoAllSubdirs,DoMatchingFiles,InsertDupes,FreeDupes)
1728
1729#pragma alloc_text(DUPES,InsertDupe,FillDupes,FreeDupes,CRCFile,CRCBlock)
1730#pragma alloc_text(DUPES,comparenamesq,comparenamesqe,comparenamesb)
1731#pragma alloc_text(DUPES,comparenamesbe,comparesizesq,comparesizesb)
Note: See TracBrowser for help on using the repository browser.