source: trunk/dll/grep.c@ 1916

Last change on this file since 1916 was 1916, checked in by Gregg Young, 11 days ago

Fix easize so that EAs larger than 32767 show their actual size instead of 32767

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