source: trunk/dll/grep.c@ 1544

Last change on this file since 1544 was 1544, checked in by Gregg Young, 15 years ago

Changes to fopen and _fsopen to allow FM2 to be loaded in high memory

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