source: trunk/dll/grep.c@ 1668

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

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

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