source: trunk/dll/grep.c@ 1665

Last change on this file since 1665 was 1665, checked in by Gregg Young, 13 years ago

Replace SleepIfNeeded with IdleIfNeeded to improve IU response during long searches; Currently it will switch back an forth between normal and idle priority.

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