source: trunk/dll/grep.c@ 1498

Last change on this file since 1498 was 1498, checked in by Gregg Young, 16 years ago

Changes to get FM2 to compile with the latest watcom 1.9 beta (mostly type casts of CHAR CONSTANT * to CHAR *). Changes to get the environment settings working everywhere again (broken by the change that moved commands to the INI); Added an environment size variable (set to 2048 which was the largest I found hard coded). Still need to find everywhere the environment size is set and use this variable.

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