source: trunk/dll/grep.c@ 1157

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

Ticket 187: Draft 1: Functions only

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