source: trunk/dll/grep.c@ 975

Last change on this file since 975 was 948, checked in by Steven Levine, 18 years ago

Rework collector progress reporting and improve performance (ticket #79)

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