source: trunk/dll/grep.c@ 1456

Last change on this file since 1456 was 1456, checked in by Steven Levine, 16 years ago

Avoid crash on Ctrl-g from collector window

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