source: trunk/dll/grep.c@ 1398

Last change on this file since 1398 was 1398, checked in by Gregg Young, 17 years ago

Move embeded strings to PCSZ variables or string table; Eliminate Error2 functions Runtime_Error with NULL format string returns "No data" error. Change declares from PSZ to PCSZ in functions where the variable isn't changed. Added btm as an executable file type in several additional places. Use fProtectOnly to prevent attempt to execute Dos and Win programs on "Protect only" installs in several additional places.

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