source: trunk/dll/grep.c@ 1208

Last change on this file since 1208 was 1208, checked in by John Small, 17 years ago

Ticket 187: Move data declarations/definitions out of fm3dll.h

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