source: trunk/dll/grep.c@ 1564

Last change on this file since 1564 was 1564, checked in by Gregg Young, 14 years ago

Rework filldir and grep directories to correctly support more than 65K records.
Collector was trapping. Added SleepIfNeeded to loops to improve WPS responsiveness.

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