source: trunk/dll/grep.c@ 1029

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

Fixed early memory free; Added free_... functions to make fortify checking easier; Added fortify scopes; Delete now moves to trash can on systems with the xworkplace trash can installed.

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