source: trunk/dll/grep.c@ 1524

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

Suppress ERROR_FILENAME_EXCED_RANGE error message on NTFS (Ticket 435)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 51.0 KB
Line 
1
2/***********************************************************************
3
4 $Id: grep.c 1524 2010-05-29 17:13:58Z 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
1026 inputFile = _fsopen(pszFileName, "rb", SH_DENYNO);
1027 if (inputFile) {
1028 pos = ftell(inputFile);
1029 while (!feof(inputFile)) {
1030 if (pos)
1031 fseek(inputFile, pos - 1024, SEEK_SET);
1032 len = fread(input, 1, 65536, inputFile);
1033 if (len >= 0) {
1034 if (*grep->stopflag)
1035 break;
1036 if (match(input,
1037 grep->searchPattern,
1038 grep->absFlag,
1039 (grep->caseFlag == FALSE),
1040 len, grep->numlines, grep->matched, !grep->findifany)) {
1041 strmatch = TRUE;
1042 break;
1043 }
1044 }
1045 else
1046 break;
1047 }
1048 fclose(inputFile);
1049 }
1050 free(input);
1051# ifdef FORTIFY
1052 Fortify_LeaveScope();
1053# endif
1054 // DosSleep(1); // 07 Feb 08 SHL
1055 }
1056 } // if
1057
1058 if (strmatch)
1059 ret = InsertGrepFile(grep, pszFileName, pffb, pitdSleep, pitdReport);
1060 return ret;
1061}
1062
1063static LONG cr3tab[] = { // CRC polynomial 0xEDB88320
1064
1065 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
1066 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
1067 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
1068 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
1069 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
1070 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
1071 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
1072 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
1073 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
1074 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
1075 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
1076 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
1077 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
1078 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
1079 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1080 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
1081 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
1082 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
1083 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
1084 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
1085 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
1086 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
1087 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
1088 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
1089 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
1090 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
1091 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
1092 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
1093 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
1094 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1095 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
1096 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
1097 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
1098 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
1099 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
1100 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
1101 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
1102 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
1103 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
1104 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
1105 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
1106 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
1107 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
1108 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
1109 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1110 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
1111 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
1112 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
1113 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
1114 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
1115 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
1116 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
1117 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
1118 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
1119 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
1120 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
1121 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
1122 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
1123 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
1124 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1125 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
1126 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
1127 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
1128 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
1129};
1130
1131LONG CRCBlock(register CHAR *str, register INT blklen, register LONG crc)
1132{
1133 while (blklen--) {
1134 crc =
1135 cr3tab[((INT) crc ^ *str) & 0xff] ^ (((ULONG) crc >> 8) & 0x00FFFFFF);
1136 str++;
1137 }
1138 return crc;
1139}
1140
1141LONG CRCFile(CHAR *pszFileName, INT *error)
1142{
1143 LONG CRC = -1L, len;
1144 FILE *fp;
1145 CHAR *buffer;
1146
1147 *error = 0;
1148 buffer = xmalloc(65535, pszSrcFile, __LINE__);
1149 if (!buffer)
1150 *error = -1;
1151 else {
1152 fp = _fsopen(pszFileName, "rb", SH_DENYNO);
1153 if (!fp)
1154 *error = -2;
1155 else {
1156 while (!feof(fp)) {
1157 len = fread(buffer, 1, 65535, fp);
1158 if (len && len < 65536L)
1159 CRC = CRCBlock(buffer, len, CRC);
1160 else
1161 break;
1162 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
1163 }
1164 fclose(fp);
1165 // DosSleep(1); // 07 Feb 08 SHL
1166 }
1167 free(buffer);
1168# ifdef FORTIFY
1169 Fortify_LeaveScope();
1170# endif
1171 }
1172 return CRC;
1173}
1174
1175static VOID FreeDupes(GREP *grep)
1176{
1177 DUPES *i, *next;
1178
1179 i = grep->dupehead;
1180 while (i) {
1181 next = i->next;
1182 if (i->name) {
1183 free(i->name);
1184 }
1185 free(i);
1186 i = next;
1187 }
1188 grep->dupehead = grep->dupelast = NULL;
1189 xfree(grep->dupenames, pszSrcFile, __LINE__);
1190 xfree(grep->dupesizes, pszSrcFile, __LINE__);
1191 grep->dupesizes = grep->dupenames = NULL;
1192# ifdef FORTIFY
1193 Fortify_LeaveScope();
1194# endif
1195}
1196
1197INT comparenamesq(const VOID *v1, const VOID *v2)
1198{
1199 DUPES *d1 = *(DUPES **) v1;
1200 DUPES *d2 = *(DUPES **) v2;
1201 CHAR *p1, *p2;
1202
1203 p1 = strrchr(d1->name, '\\');
1204 if (p1)
1205 p1++;
1206 else
1207 p1 = d1->name;
1208 p2 = strrchr(d2->name, '\\');
1209 if (p2)
1210 p2++;
1211 else
1212 p2 = d2->name;
1213 return stricmp(p1, p2);
1214}
1215
1216INT comparenamesqe(const VOID *v1, const VOID *v2)
1217{
1218 DUPES *d1 = *(DUPES **) v1;
1219 DUPES *d2 = *(DUPES **) v2;
1220 CHAR *p1, *p2, *p1e, *p2e, e1, e2;
1221 INT ret;
1222
1223 p1 = strrchr(d1->name, '\\');
1224 if (p1)
1225 p1++;
1226 else
1227 p1 = d1->name;
1228 p1e = strrchr(p1, '.');
1229 if (p1e) {
1230 e1 = *p1e;
1231 *p1e = 0;
1232 }
1233 p2 = strrchr(d2->name, '\\');
1234 if (p2)
1235 p2++;
1236 else
1237 p2 = d2->name;
1238 p2e = strrchr(p2, '.');
1239 if (p2e) {
1240 e2 = *p2e;
1241 *p2e = 0;
1242 }
1243 ret = stricmp(p1, p2);
1244 if (p1e)
1245 *p1e = e1;
1246 if (p2e)
1247 *p2e = e2;
1248 return ret;
1249}
1250
1251INT comparesizesq(const void *v1, const void *v2)
1252{
1253 DUPES *d1 = *(DUPES **) v1;
1254 DUPES *d2 = *(DUPES **) v2;
1255
1256 return (d1->size > d2->size) ? 1 : (d1->size == d2->size) ? 0 : -1;
1257}
1258
1259INT comparenamesb(const void *v1, const void *v2)
1260{
1261 DUPES *d1 = (DUPES *) v1;
1262 DUPES *d2 = *(DUPES **) v2;
1263 CHAR *p1, *p2;
1264
1265 p1 = strrchr(d1->name, '\\');
1266 if (p1)
1267 p1++;
1268 else
1269 p1 = d1->name;
1270 p2 = strrchr(d2->name, '\\');
1271 if (p2)
1272 p2++;
1273 else
1274 p2 = d2->name;
1275 return stricmp(p1, p2);
1276}
1277
1278INT comparenamesbe(const VOID *v1, const VOID *v2)
1279{
1280 DUPES *d1 = (DUPES *) v1;
1281 DUPES *d2 = *(DUPES **) v2;
1282 CHAR *p1, *p2, *p1e, *p2e, e1, e2;
1283 INT ret;
1284
1285 p1 = strrchr(d1->name, '\\');
1286 if (p1)
1287 p1++;
1288 else
1289 p1 = d1->name;
1290 p1e = strrchr(p1, '.');
1291 if (p1e) {
1292 e1 = *p1e;
1293 *p1e = 0;
1294 }
1295 p2 = strrchr(d2->name, '\\');
1296 if (p2)
1297 p2++;
1298 else
1299 p2 = d2->name;
1300 p2e = strrchr(p2, '.');
1301 if (p2e) {
1302 e2 = *p2e;
1303 *p2e = 0;
1304 }
1305 ret = stricmp(p1, p2);
1306 if (p1e)
1307 *p1e = e1;
1308 if (p2e)
1309 *p2e = e2;
1310 return ret;
1311}
1312
1313INT comparesizesb(const VOID *v1, const VOID *v2)
1314{
1315 DUPES *d1 = (DUPES *) v1;
1316 DUPES *d2 = *(DUPES **) v2;
1317
1318 return (d1->size > d2->size) ? 1 : (d1->size == d2->size) ? 0 : -1;
1319}
1320
1321static VOID FillDupes(GREP *grep,
1322 ITIMER_DESC *pitdSleep,
1323 ITIMER_DESC *pitdReport)
1324{
1325 DUPES *c, *i, **r;
1326 register CHAR *pc, *pi;
1327 CHAR **list = NULL;
1328 UINT numfiles = 0, numalloced = 0;
1329 INT error;
1330 ULONG x;
1331 ULONG y;
1332 // ULONG cntr = 1000; // 09 Feb 08 SHL
1333
1334 // if (grep->CRCdupes) // 09 Feb 08 SHL
1335 // cntr = 100; // 09 Feb 08 SHL
1336 x = 0;
1337 for (i = grep->dupehead; i; i = i->next)
1338 x++; // Count
1339
1340 if (x) {
1341 if (!hwndStatus)
1342 WinSetWindowText(grep->hwndCurFile, (CHAR *) GetPString(IDS_GREPDUPESORTINGTEXT));
1343 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1344 WinSetWindowText(hwndStatus, (CHAR *) GetPString(IDS_GREPDUPESORTINGTEXT));
1345 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
1346 grep->dupenames = xmalloc(sizeof(DUPES *) * (x + 1), pszSrcFile, __LINE__);
1347 if (!grep->nosizedupes)
1348 grep->dupesizes = xmalloc(sizeof(DUPES *) * (x + 1), pszSrcFile, __LINE__);
1349 if (grep->dupenames && (grep->nosizedupes || grep->dupesizes)) {
1350 y = 0;
1351 for (i = grep->dupehead; i; i = i->next) {
1352 grep->dupenames[y] = i;
1353 if (!grep->nosizedupes)
1354 grep->dupesizes[y] = i;
1355 y++;
1356 }
1357 grep->dupenames[y] = NULL; // Mark end
1358 if (!grep->nosizedupes)
1359 grep->dupesizes[y] = NULL;
1360
1361 InitITimer(pitdSleep, 0); // Reset rate estimator
1362 SleepIfNeeded(pitdSleep, 1);
1363 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
1364
1365 qsort(grep->dupenames,
1366 x,
1367 sizeof(DUPES *),
1368 grep->ignoreextdupes ? comparenamesqe : comparenamesq);
1369 SleepIfNeeded(pitdSleep, 1);
1370 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
1371 if (!grep->nosizedupes) {
1372 qsort(grep->dupesizes, x, sizeof(DUPES *), comparesizesq);
1373 SleepIfNeeded(pitdSleep, 1);
1374 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
1375 }
1376
1377 if (!hwndStatus)
1378 WinSetWindowText(grep->hwndCurFile, (CHAR *) GetPString(IDS_GREPDUPECOMPARINGTEXT));
1379 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1380 WinSetWindowText(hwndStatus, (CHAR *) GetPString(IDS_GREPDUPECOMPARINGTEXT));
1381
1382 InitITimer(pitdSleep, 0); // Reset rate estimator
1383 i = grep->dupehead;
1384 y = 0;
1385 while (i) {
1386 if (*grep->stopflag)
1387 break;
1388 SleepIfNeeded(pitdSleep, 1); // 07 Feb 08 SHL
1389 if (!(i->flags & GF_SKIPME)) {
1390 r = (DUPES **) bsearch(i, grep->dupenames, x, sizeof(DUPES *),
1391 ((grep->ignoreextdupes) ? comparenamesbe :
1392 comparenamesb));
1393 if (r) {
1394 while (r > grep->dupenames && ((grep->ignoreextdupes) ?
1395 !comparenamesqe((r - 1), &i) :
1396 !comparenamesq((r - 1), &i)))
1397 r--;
1398 while (*r && ((grep->ignoreextdupes) ?
1399 !comparenamesqe(r, &i) : !comparenamesq(r, &i))) {
1400 if (*r == i || ((*r)->flags & (GF_INSERTED | GF_SKIPME))) {
1401 r++;
1402 continue;
1403 }
1404 if (grep->CRCdupes) {
1405 if ((*r)->CRC == -1L) {
1406 (*r)->CRC = CRCFile((*r)->name, &error);
1407 if (error)
1408 (*r)->CRC = -1L;
1409 else if ((*r)->CRC == -1L)
1410 (*r)->CRC = 0L;
1411 }
1412 if (i->CRC == -1L) {
1413 i->CRC = CRCFile(i->name, &error);
1414 if (error)
1415 i->CRC = -1L;
1416 else if (i->CRC == -1L)
1417 i->CRC = 0L;
1418 }
1419 if (((*r)->size != i->size) || ((*r)->CRC != -1L &&
1420 i->CRC != -1L
1421 && (*r)->CRC != i->CRC)) {
1422 r++;
1423 continue;
1424 }
1425 }
1426 if (!AddToList((*r)->name, &list, &numfiles, &numalloced)) {
1427 (*r)->flags |= GF_INSERTED;
1428 if (grep->sayfiles) {
1429 if (!hwndStatus)
1430 WinSetWindowText(grep->hwndFiles, (*r)->name);
1431 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1432 WinSetWindowText(hwndStatus, (*r)->name);
1433 }
1434 if ((*r)->size == i->size &&
1435 (i->date.year == (*r)->date.year &&
1436 i->date.month == (*r)->date.month &&
1437 i->date.day == (*r)->date.day &&
1438 i->time.hours == (*r)->time.hours &&
1439 i->time.minutes == (*r)->time.minutes &&
1440 i->time.twosecs == (*r)->time.twosecs))
1441 (*r)->flags |= GF_SKIPME;
1442 }
1443 if (!(i->flags & (GF_INSERTED | GF_SKIPME))) {
1444 if (!AddToList(i->name, &list, &numfiles, &numalloced)) {
1445 i->flags |= GF_INSERTED;
1446 if ((*r)->flags & GF_SKIPME)
1447 i->flags |= GF_SKIPME;
1448 }
1449 }
1450 r++;
1451 }
1452 }
1453 if (!grep->nosizedupes) {
1454 r = (DUPES **) bsearch(i,
1455 grep->dupesizes,
1456 x, sizeof(DUPES *), comparesizesb);
1457 if (r) {
1458 while (r > grep->dupesizes && !comparesizesq((r - 1), &i))
1459 r--;
1460 while (*r && !comparesizesq(r, &i)) {
1461 if (*r == i || ((*r)->flags & (GF_INSERTED | GF_SKIPME)) ||
1462 (i->date.year != (*r)->date.year ||
1463 i->date.month != (*r)->date.month ||
1464 i->date.day != (*r)->date.day ||
1465 i->time.hours != (*r)->time.hours ||
1466 i->time.minutes != (*r)->time.minutes ||
1467 i->time.twosecs != (*r)->time.twosecs)) {
1468 r++;
1469 continue;
1470 }
1471 if (grep->CRCdupes) {
1472 if ((*r)->CRC == -1L) {
1473 (*r)->CRC = CRCFile((*r)->name, &error);
1474 if (error)
1475 (*r)->CRC = -1L;
1476 else if ((*r)->CRC == -1L)
1477 (*r)->CRC = 0L;
1478 }
1479 if (i->CRC == -1L) {
1480 i->CRC = CRCFile(i->name, &error);
1481 if (error)
1482 i->CRC = -1L;
1483 else if (i->CRC == -1L)
1484 i->CRC = 0L;
1485 }
1486 if ((*r)->CRC != -1L && i->CRC != -1L &&
1487 (*r)->CRC != i->CRC) {
1488 *r += 1;
1489 continue;
1490 }
1491 }
1492 if (!AddToList((*r)->name, &list, &numfiles, &numalloced)) {
1493 if (grep->sayfiles) {
1494 if (!hwndStatus)
1495 WinSetWindowText(grep->hwndCurFile, (*r)->name);
1496 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1497 WinSetWindowText(hwndStatus, (*r)->name);
1498 }
1499 (*r)->flags |= GF_INSERTED;
1500 if (((grep->ignoreextdupes) ?
1501 comparenamesqe(r, &i) : comparenamesq(r, &i)))
1502 (*r)->flags |= GF_SKIPME;
1503 }
1504 if (!(i->flags & (GF_INSERTED | GF_SKIPME))) {
1505 if (!AddToList(i->name, &list, &numfiles, &numalloced)) {
1506 i->flags |= GF_INSERTED;
1507 if ((*r)->flags & GF_SKIPME)
1508 i->flags |= GF_SKIPME;
1509 }
1510 }
1511 r++;
1512 }
1513 }
1514 }
1515 }
1516 i = i->next;
1517 y++;
1518 // 08 Feb 08 SHL
1519 if (IsITimerExpired(pitdReport)) {
1520 CHAR s[44];
1521 sprintf(s, GetPString(IDS_GREPDUPECHECKPROGTEXT), y, grep->numfiles);
1522 if (!hwndStatus)
1523 WinSetWindowText(grep->hwndCurFile, s);
1524 else {
1525 if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1526 WinSetWindowText(hwndStatus, s);
1527 }
1528 }
1529 } // while
1530 }
1531 else {
1532 // Insufficient memory - fall back to slow method - fixme to saymsg?
1533 if (!fErrorBeepOff)
1534 DosBeep(50, 100);
1535 if (!hwndStatus)
1536 WinSetWindowText(grep->hwndCurFile, (CHAR *) GetPString(IDS_GREPDUPECOMPARINGTEXT));
1537 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1538 WinSetWindowText(hwndStatus, (CHAR *) GetPString(IDS_GREPDUPECOMPARINGTEXT));
1539 x = y = 0;
1540 xfree(grep->dupenames, pszSrcFile, __LINE__);
1541 grep->dupenames = NULL;
1542 xfree(grep->dupesizes, pszSrcFile, __LINE__);
1543 grep->dupesizes = NULL;
1544# ifdef FORTIFY
1545 Fortify_LeaveScope();
1546# endif
1547
1548 InitITimer(pitdSleep, 0); // Reset rate estimator
1549 i = grep->dupehead;
1550 while (i) {
1551 if (*grep->stopflag)
1552 break;
1553 SleepIfNeeded(pitdSleep, 1);
1554 if (!(i->flags & GF_SKIPME)) {
1555 if (IsITimerExpired(pitdReport)) {
1556 // if (!(y % cntr)) { }
1557 CHAR s[44];
1558 sprintf(s, GetPString(IDS_GREPDUPECHECKPROGTEXT), y, grep->numfiles);
1559 if (!hwndStatus)
1560 WinSetWindowText(grep->hwndCurFile, s);
1561 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1562 WinSetWindowText(hwndStatus, s);
1563 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
1564 }
1565 y++;
1566 pi = strrchr(i->name, '\\');
1567 if (pi)
1568 pi++;
1569 else
1570 pi = i->name;
1571 c = grep->dupehead;
1572 while (c) {
1573 if (*grep->stopflag)
1574 break;
1575 if (c != i && !(c->flags & (GF_INSERTED | GF_SKIPME))) {
1576 x++;
1577 pc = strrchr(c->name, '\\');
1578 if (pc)
1579 pc++;
1580 else
1581 pc = c->name;
1582 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
1583 if (grep->CRCdupes) {
1584 if (grep->CRCdupes) {
1585 if (c->CRC == -1L) {
1586 c->CRC = CRCFile(c->name, &error);
1587 if (error)
1588 c->CRC = -1L;
1589 else if (c->CRC == -1L)
1590 c->CRC = 0L;
1591 }
1592 if (i->CRC == -1L) {
1593 i->CRC = CRCFile(i->name, &error);
1594 if (error)
1595 i->CRC = -1L;
1596 else if (i->CRC == -1L)
1597 i->CRC = 0L;
1598 }
1599 if ((c->size != i->size) || (c->CRC != -1L &&
1600 i->CRC != -1L
1601 && c->CRC != i->CRC)) {
1602 c = c->next;
1603 continue;
1604 }
1605 }
1606 }
1607 if (AddToList(c->name, &list, &numfiles, &numalloced))
1608 goto BreakOut; // Failed
1609 if (!(i->flags & GF_INSERTED)) {
1610 if (AddToList(i->name, &list, &numfiles, &numalloced))
1611 goto BreakOut; // Failed
1612 }
1613 if (grep->sayfiles) {
1614 if (!hwndStatus)
1615 WinSetWindowText(grep->hwndCurFile, pc);
1616 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1617 WinSetWindowText(hwndStatus, pc);
1618 }
1619 c->flags |= GF_INSERTED;
1620 i->flags |= GF_INSERTED;
1621 if (!stricmp(pc, pi)) {
1622 c->flags |= GF_SKIPME;
1623 i->flags |= GF_SKIPME;
1624 }
1625 }
1626 // else if (!(x % 100)) // 07 Feb 08 SHL
1627 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
1628 }
1629 c = c->next;
1630 }
1631 }
1632 i = i->next;
1633 } // while
1634 }
1635 }
1636BreakOut:
1637 FreeDupes(grep);
1638 if (numfiles && list) {
1639 if (!PostMsg(grep->hwndFiles,
1640 WM_COMMAND,
1641 MPFROM2SHORT(IDM_COLLECTOR, 0),
1642 MPFROMP(list)))
1643 FreeList(list);
1644 }
1645 else
1646 DosPostEventSem(CompactSem);
1647}
1648
1649static BOOL InsertDupe(GREP *grep, CHAR *dir, FILEFINDBUF4L *pffb)
1650{
1651 DUPES *info;
1652
1653 if (*dir) {
1654 info = xmallocz(sizeof(DUPES), pszSrcFile, __LINE__);
1655 if (!info)
1656 return FALSE;
1657
1658 info->name = xstrdup(dir, pszSrcFile, __LINE__);
1659 if (!info->name) {
1660 free(info);
1661# ifdef FORTIFY
1662 Fortify_LeaveScope();
1663# endif
1664 return FALSE;
1665 }
1666
1667 info->size = pffb->cbFile;
1668 info->date = pffb->fdateLastWrite;
1669 info->time = pffb->ftimeLastWrite;
1670 info->CRC = -1L;
1671 grep->numfiles++;
1672 if (!grep->dupehead)
1673 grep->dupehead = info;
1674 if (grep->dupelast)
1675 grep->dupelast->next = info;
1676 grep->dupelast = info;
1677 info->next = NULL;
1678 }
1679 return TRUE;
1680}
1681
1682#pragma alloc_text(GREP,InsertGrepFile,DoOneFile,DoInsertion,freegreplist)
1683#pragma alloc_text(GREP,SecsSince1980,match,mmatch,GrepThread)
1684#pragma alloc_text(GREP,DoAllSubdirs,DoMatchingFiles,InsertDupes,FreeDupes)
1685
1686#pragma alloc_text(DUPES,InsertDupe,FillDupes,FreeDupes,CRCFile,CRCBlock)
1687#pragma alloc_text(DUPES,comparenamesq,comparenamesqe,comparenamesb)
1688#pragma alloc_text(DUPES,comparenamesbe,comparesizesq,comparesizesb)
Note: See TracBrowser for help on using the repository browser.