source: trunk/dll/grep.c@ 1223

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

Ticket 187: Moved typedef's and some #define's from fm3dll.h

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