source: trunk/dll/grep.c@ 1017

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

fortify updates for threads dble free fix

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