source: trunk/dll/grep.c@ 1303

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

Last part of remove or replace with a mutex semaphore DosEnterCriSec where appropriate. (Ticket 308) Note the partial commits for this ticket won't build without this.

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