source: trunk/dll/grep.c@ 1668

Last change on this file since 1668 was 1668, checked in by Gregg Young, 13 years ago

Always sort "Find Dups" by filename in the collector. (Ticket 8)

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