source: trunk/dll/grep.c@ 1780

Last change on this file since 1780 was 1780, checked in by Gregg Young, 11 years ago

Fixed errors found by cppcheck. Most had the potential to cause difficult to reproduce traps. Also fixed retry code for failure to create an archive work directory and the failure of the mailto code to drop trailing >.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 46.0 KB
RevLine 
[51]1
2/***********************************************************************
3
4 $Id: grep.c 1780 2014-06-28 18:05:22Z 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"
[2]83
[948]84static VOID DoAllSubdirs(GREP *grep,
[1707]85 CHAR *searchPath,
86 BOOL recursing,
87 char **fileMasks,
88 UINT numFileMasks,
89 ITIMER_DESC *pitdSleep,
90 ITIMER_DESC *pitdReport);
[948]91static INT DoMatchingFiles(GREP *grep,
[1707]92 CHAR *path,
93 CHAR **fileMasks,
94 UINT numFileMasks,
95 ITIMER_DESC *pitdSleep,
96 ITIMER_DESC *pitdReport);
[948]97static BOOL DoOneFile(GREP *grep,
[1707]98 CHAR *fileName,
99 FILEFINDBUF4L *pffb,
100 ITIMER_DESC *pitdSleep,
101 ITIMER_DESC *pitdReport);
[948]102static BOOL DoInsertion(GREP *grep,
[1707]103 ITIMER_DESC *pitdSleep,
104 ITIMER_DESC *pitdReport);
[841]105static BOOL InsertDupe(GREP *grep, CHAR *dir, FILEFINDBUF4L *pffb);
[948]106static VOID FillDupes(GREP *grep,
[1707]107 ITIMER_DESC *pitdSleep,
108 ITIMER_DESC *pitdReport);
[948]109
[783]110static VOID FreeDupes(GREP *grep);
[2]111
112#define GREPCHARS "*?[] \\"
113
114#define isleap(year) ((((year%4)==0) && ((year%100)!=0)) || \
[1707]115 ((year%400)==0))
[2]116
[1208]117// Data definitions
118#pragma data_seg(DATA2)
119static PSZ pszSrcFile = __FILE__;
[551]120static INT monthdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
[2]121
[1208]122#pragma data_seg(GLOBAL1)
123HWND hwndStatus;
124
125
[948]126ULONG SecsSince1980(FDATE *date, FTIME *time)
[51]127{
[841]128 ULONG total = 0;
[948]129 UINT x;
[2]130
[551]131 for (x = 1980; x < date->year + 1980; x++) {
132 if (isleap(x))
[841]133 total += (366 * (24 * 60 * 60));
[2]134 else
[841]135 total += (365 * (24 * 60 * 60));
[2]136 }
[551]137 for (x = 1; x < date->month; x++) {
138 if (x == 2 && isleap(date->year + 1980))
[841]139 total += (29 * (24 * 60 * 60));
[2]140 else
[841]141 total += ((long)monthdays[x - 1] * (24 * 60 * 60));
[2]142 }
[841]143 total += (((long)date->day - 1) * (24 * 60 * 60));
144 total += ((long)time->hours * (60 * 60));
145 total += ((long)time->minutes * 60);
146 total += ((long)time->twosecs * 2);
[2]147 return total;
148}
149
[1673]150/**
[2]151 * this function originally from C_ECHO's Snippets -- modified
152 * brute force methodology
153 */
154
[948]155static BOOL m_match(CHAR *string, CHAR *pattern, BOOL absolute, BOOL ignore,
[1707]156 LONG len)
[551]157{
[783]158 // return TRUE if pattern found in string
[2]159 register CHAR *tn = pattern;
[551]160 register LONG len2 = 0;
161 LONG lastlen = 0;
162 CHAR lo, hi;
[2]163
[551]164 if (len && string && pattern) {
[1157]165 if (absolute) // no pattern matching
[551]166 return (findstring(pattern, strlen(pattern), string, len,
[1707]167 (ignore == FALSE)) != NULL);
[2]168
[551]169 while (*tn && len2 < len) {
170 switch (*tn) {
171 case ' ':
[1707]172 while (*tn == ' ')
173 tn++;
174 while (len2 < len && isspace(string[len2]))
175 len2++;
176 break;
[2]177
[551]178 case '*':
[1707]179 while (*tn == '*' || *tn == '?')
180 tn++;
181 if (!*tn)
182 return TRUE;
183 if (ignore) {
184 while (len2 < len && string[len2] != *tn)
185 len2++;
186 }
187 else {
188 while (len2 < len && toupper(string[len2] != *tn))
189 len2++;
190 }
191 break;
[2]192
[551]193 case '[':
[1707]194 tn++;
195 if (!*tn)
196 return FALSE;
197 lo = *tn;
198 tn++;
199 if (*tn != '-')
200 return FALSE;
201 tn++;
202 if (!*tn)
203 return FALSE;
204 hi = *tn;
205 tn++;
206 if (*tn != ']')
207 return FALSE;
208 tn++;
209 if (ignore) {
210 if ((toupper(string[len2]) >= toupper(lo)) &&
211 (toupper(string[len2]) <= toupper(hi)))
212 len2++;
213 else {
214 tn = pattern;
215 len2 = lastlen = lastlen + 1;
216 }
217 }
218 else {
219 if ((string[len2] >= lo) && (string[len2] <= hi))
220 len2++;
221 else {
222 tn = pattern;
223 len2 = lastlen = lastlen + 1;
224 }
225 }
226 break;
[2]227
[551]228 case '?':
[1707]229 tn++;
230 len2++;
231 break;
[2]232
[551]233 case '\\':
[1707]234 tn++;
235 if (!*tn)
236 return FALSE;
237 // else intentional fallthru
[551]238 default:
[1707]239 if (ignore) {
240 if (toupper(*tn) == toupper(string[len2])) {
241 tn++;
242 len2++;
243 }
244 else {
245 tn = pattern;
246 len2 = lastlen = lastlen + 1;
247 }
248 }
249 else {
250 if (*tn == string[len2]) {
251 tn++;
252 len2++;
253 }
254 else {
255 tn = pattern;
256 len2 = lastlen = lastlen + 1;
257 }
258 }
259 break;
[2]260 }
261 }
[551]262 while (*tn == '*')
[2]263 tn++;
264
265 if (!*tn)
266 return TRUE;
267 }
268 return FALSE;
269}
270
[948]271static BOOL match(CHAR *string, CHAR *patterns, BOOL absolute, BOOL ignore,
[1707]272 LONG len, ULONG numlines, CHAR *matched, BOOL matchall)
[551]273{
274 BOOL ret = FALSE;
[2]275 register CHAR *p;
276 register ULONG x = 0;
277
278 p = patterns;
[551]279 while (!ret && *p) {
280 ret = m_match(string, p, absolute, ignore, len);
281 if (matchall && ret)
[2]282 break;
[551]283 if (matched && ret && x < numlines)
[2]284 matched[x] = 1;
[1157]285 p += strlen(p); // check each pattern in 0-terminated list
[2]286 p++;
287 x++;
288 }
289 return ret;
290}
291
[948]292VOID GrepThread(VOID *arg)
[51]293{
[551]294 HAB ghab;
295 HMQ ghmq;
296 GREP grep;
[948]297 UINT x;
[1707]298 UINT numFileMasks;
299 static CHAR *fileMasks[512]; // 06 Feb 08 SHL FIXME to not be static
[551]300 CHAR *p, *pp, searchPath[CCHMAXPATH * 2];
[2]301
[1157]302 ITIMER_DESC itdSleep = { 0 }; // 06 Feb 08 SHL
[948]303 ITIMER_DESC itdReport = { 0 };
304
[783]305 if (!arg) {
[1398]306 Runtime_Error(pszSrcFile, __LINE__, NULL);
[2]307 return;
[783]308 }
309
[1038]310# ifdef FORTIFY
311 Fortify_EnterScope();
[1063]312# endif
[783]313 grep = *(GREP *)arg;
[1157]314 *grep.stopflag = 0; // reset thread-killing flag
[2]315 DosError(FERR_DISABLEHARDERR);
316 priority_normal();
317
318 ghab = WinInitialize(0);
[551]319 if (ghab) {
[2]320 grep.ghab = ghab;
[551]321 ghmq = WinCreateMsgQueue(ghab, 0);
322 if (ghmq) {
323 WinCancelShutdown(ghmq, TRUE);
[528]324 IncrThreadUsage();
[1157]325 // DosSleep(100); //05 Aug 07 GKY 128 // 07 Feb 08 SHL
[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 //SleepIfNeeded(pitdSleep, 1);
791 if (pci == NULL && ulRecsToInsert) {
792 memset(&ri, 0, sizeof(RECORDINSERT));
793 ri.cb = sizeof(RECORDINSERT);
794 ri.pRecordOrder = (PRECORDCORE) CMA_END;
795 ri.pRecordParent = (PRECORDCORE) NULL;
796 ri.zOrder = (USHORT) CMA_TOP;
797 ri.cRecordsInsert = ulRecsToInsert;
798 ri.fInvalidateRecord = TRUE;
799 WinSendMsg(grep->hwndFiles,
[1707]800 CM_INSERTRECORD, MPFROMP(pciFirst), MPFROMP(&ri));
[1564]801 if (dcd) {
[1707]802 DosRequestMutexSem(hmtxFM2Globals, SEM_INDEFINITE_WAIT);
803 dcd->ullTotalBytes += grep->insertedbytes;
804 DosReleaseMutexSem(hmtxFM2Globals);
[1564]805 }
806 pciFirst = NULL;
[2]807 }
[948]808 SleepIfNeeded(pitdSleep, 1);
[1564]809 }//for
[1157]810 // if (grep->toinsert == FilesToGet) // 07 Feb 08 SHL
811 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
[2]812 freegreplist(grep);
[551]813 PostMsg(grep->hwndFiles, UM_RESCAN, MPVOID, MPVOID);
[2]814 return TRUE;
815}
816
[948]817/**
818 * Insert file ffb and directory name into lists
819 */
820
821static BOOL InsertGrepFile(GREP *grep,
[1707]822 CHAR *pszFileName,
823 PFILEFINDBUF4L pffb,
824 ITIMER_DESC *pitdSleep,
825 ITIMER_DESC *pitdReport)
[51]826{
[783]827 PSZ p;
828 CHAR szDirectory[CCHMAXPATH];
[2]829
[948]830 if (!WinIsWindow(grep->ghab, grep->hwndFiles)) {
831 // Window closed - clean up and go away
832 freegreplist(grep);
833 }
834 else {
[2]835 grep->numfiles++;
[948]836 strcpy(szDirectory, pszFileName);
[551]837 p = strrchr(szDirectory, '\\');
[948]838
[551]839 if (p) {
[948]840 // Got directory
[551]841 if (p < szDirectory + 4)
[1707]842 p++; // Include root backslash
[2]843 *p = 0;
[948]844
[551]845 if (!grep->insertffb) {
[1707]846 // Allocate 1 extra for end marker?
847 grep->insertffb = xmallocz(sizeof(PFILEFINDBUF4L) * (FilesToGet + 1),
848 pszSrcFile, __LINE__);
849 if (!grep->insertffb)
850 return FALSE;
851 grep->dir = xmallocz(sizeof(CHAR *) * (FilesToGet + 1),
852 pszSrcFile, __LINE__);
853 if (!grep->dir) {
854 free(grep->insertffb);
[1063]855# ifdef FORTIFY
[1707]856 Fortify_LeaveScope();
[1063]857# endif
[1707]858 return FALSE;
859 }
[2]860 }
[948]861
[551]862 grep->insertffb[grep->toinsert] =
[1707]863 xmalloc(sizeof(FILEFINDBUF4L), pszSrcFile, __LINE__);
[551]864 if (!grep->insertffb[grep->toinsert])
[1707]865 return FALSE;
[841]866 memcpy(grep->insertffb[grep->toinsert], pffb, sizeof(FILEFINDBUF4L));
[948]867
[551]868 grep->dir[grep->toinsert] = xstrdup(szDirectory, pszSrcFile, __LINE__);
869 if (!grep->dir) {
[1707]870 free(grep->insertffb[grep->toinsert]);
[1063]871# ifdef FORTIFY
[1707]872 Fortify_LeaveScope();
[1063]873# endif
[1707]874 return FALSE;
[2]875 }
[948]876
[783]877 grep->insertedbytes += pffb->cbFile + CBLIST_TO_EASIZE(pffb->cbList);
[2]878 grep->toinsert++;
[1471]879 // 07 Oct 09 SHL honor sync updates
880 if (grep->toinsert == FilesToGet || fSyncUpdates)
[1707]881 return DoInsertion(grep, pitdSleep, pitdReport);
[2]882 return TRUE;
883 }
884 }
885 return FALSE;
886}
887
[948]888/**
889 * Check file matches search criteria
890 */
891
892static BOOL DoOneFile(GREP *grep,
[1707]893 CHAR *pszFileName,
894 FILEFINDBUF4L *pffb,
895 ITIMER_DESC *pitdSleep,
896 ITIMER_DESC *pitdReport)
[51]897{
[783]898 // process a single file
[551]899 CHAR *input;
900 FILE *inputFile;
901 ULONG pos;
902 BOOL ret = FALSE, strmatch = FALSE;
[2]903
904 grep->fileCount++;
[948]905 if (grep->sayfiles) {
906 if (!hwndStatus)
907 WinSetWindowText(grep->hwndCurFile, pszFileName);
908 else {
909 if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
[1707]910 WinSetWindowText(hwndStatus, pszFileName);
[948]911 }
912 }
[2]913
[551]914 if (grep->greaterthan || grep->lessthan) {
[2]915
[551]916 BOOL keep = TRUE;
[2]917 ULONG adjsize;
918
[783]919 adjsize = pffb->cbFile + (grep->searchEAs ? CBLIST_TO_EASIZE(pffb->cbList) : 0);
[551]920 if (grep->greaterthan) {
921 if (adjsize < grep->greaterthan)
[1707]922 keep = FALSE;
[2]923 }
[551]924 if (keep && grep->lessthan) {
925 if (adjsize > grep->lessthan)
[1707]926 keep = FALSE;
[2]927 }
[551]928 if (!keep)
[2]929 return ret;
930 }
931
[551]932 if (grep->newerthan || grep->olderthan) {
[2]933
[551]934 BOOL keep = TRUE;
[2]935 ULONG numsecs;
936
[783]937 numsecs = SecsSince1980(&pffb->fdateLastWrite, &pffb->ftimeLastWrite);
[551]938 if (grep->newerthan) {
939 if (numsecs < grep->newerthan)
[1707]940 keep = FALSE;
[2]941 }
[551]942 if (keep && grep->olderthan) {
943 if (numsecs > grep->olderthan)
[1707]944 keep = FALSE;
[2]945 }
[551]946 if (!keep)
[2]947 return ret;
948 }
949
[1157]950 if ((!grep->searchEAs && !grep->searchFiles) || !*grep->searchPattern) // just a find
[948]951 return InsertGrepFile(grep, pszFileName, pffb, pitdSleep, pitdReport);
[2]952
[551]953 if (grep->searchEAs) {
[2]954
[551]955 HOLDFEA *head, *info;
956 USHORT type, len;
957 BOOL alltext;
958 CHAR *data, temp;
[2]959
[948]960 head = GetFileEAs(pszFileName, FALSE, TRUE);
[551]961 if (head) {
[2]962 info = head;
[551]963 while (info && !strmatch) {
[1707]964 alltext = TRUE;
965 switch (*(USHORT *)info->value) {
966 case EAT_ASCII:
967 if (match(info->value + (sizeof(USHORT) * 2),
968 grep->searchPattern, grep->absFlag,
969 grep->caseFlag == FALSE,
970 info->cbValue - (sizeof(USHORT) * 2),
971 grep->numlines,
972 grep->matched,
973 !grep->findifany)) {
974 strmatch = TRUE;
975 }
976 break;
977 case EAT_MVST:
978 type = *(USHORT *)(info->value + (sizeof(USHORT) * 3));
979 if (type == EAT_ASCII) {
980 data = info->value + (sizeof(USHORT) * 4);
981 len = *(USHORT *) data;
982 data += sizeof(USHORT);
983 while ((data - info->value) + len <= info->cbValue) {
984 temp = *(data + len);
985 *(data + len) = 0;
986 if (match(data,
987 grep->searchPattern,
988 grep->absFlag,
989 (grep->caseFlag == FALSE),
990 len,
991 grep->numlines, grep->matched, !grep->findifany)) {
992 strmatch = TRUE;
993 break;
994 }
995 data += len;
996 if (data - info->value >= info->cbValue)
997 break;
998 *data = temp;
999 len = *(USHORT *) data;
1000 data += sizeof(USHORT);
1001 }
1002 }
1003 break;
1004 case EAT_MVMT:
1005 data = info->value + (sizeof(USHORT) * 3);
1006 type = *(USHORT *) data;
1007 data += sizeof(USHORT);
1008 len = *(USHORT *) data;
1009 data += sizeof(USHORT);
1010 while ((data - info->value) - len <= info->cbValue) {
1011 if (type != EAT_ASCII) {
1012 alltext = FALSE;
1013 break;
1014 }
1015 data += len;
1016 if (data - info->value >= info->cbValue)
1017 break;
1018 type = *(USHORT *) data;
1019 data += sizeof(USHORT);
1020 len = *(USHORT *) data;
1021 data += sizeof(USHORT);
1022 }
1023 if (alltext) {
1024 data = info->value + (sizeof(USHORT) * 3);
1025 type = *(USHORT *) data;
1026 data += sizeof(USHORT);
1027 len = *(USHORT *) data;
1028 data += sizeof(USHORT);
1029 while ((data - info->value) - len <= info->cbValue) {
1030 temp = *(data + len);
1031 *(data + len) = 0;
1032 if (match(data,
1033 grep->searchPattern,
1034 grep->absFlag,
1035 (grep->caseFlag == FALSE),
1036 len,
1037 grep->numlines, grep->matched, !grep->findifany)) {
1038 strmatch = TRUE;
1039 break;
1040 }
1041 data += len;
1042 *data = temp;
1043 if (data - info->value >= info->cbValue)
1044 break;
1045 type = *(USHORT *) data;
1046 data += sizeof(USHORT);
1047 len = *(USHORT *) data;
1048 data += sizeof(USHORT);
1049 }
1050 }
1051 break;
1052 default:
1053 break;
1054 }
1055 info = info->next;
[1157]1056 } // while
[2]1057 Free_FEAList(head);
[1157]1058 // DosSleep(1); // 07 Feb 08 SHL
[2]1059 }
1060 }
1061
[551]1062 if (grep->searchFiles) {
1063 input = xmalloc(65537, pszSrcFile, __LINE__);
1064 if (input) {
[2]1065 LONG len;
[1544]1066 CHAR *moderb = "rb";
[551]1067
[1544]1068 inputFile = xfsopen(pszFileName, moderb, SH_DENYNO, pszSrcFile, __LINE__, TRUE);
[350]1069 if (inputFile) {
[1707]1070 pos = ftell(inputFile);
1071 while (!feof(inputFile)) {
1072 if (pos)
1073 fseek(inputFile, pos - 1024, SEEK_SET);
1074 len = fread(input, 1, 65536, inputFile);
1075 if (len >= 0) {
1076 if (*grep->stopflag)
1077 break;
1078 if (match(input,
1079 grep->searchPattern,
1080 grep->absFlag,
1081 (grep->caseFlag == FALSE),
1082 len, grep->numlines, grep->matched, !grep->findifany)) {
1083 strmatch = TRUE;
1084 break;
1085 }
1086 }
1087 else
1088 break;
1089 }
1090 fclose(inputFile);
[2]1091 }
[1039]1092 free(input);
[1063]1093# ifdef FORTIFY
1094 Fortify_LeaveScope();
1095# endif
[1157]1096 // DosSleep(1); // 07 Feb 08 SHL
[2]1097 }
[689]1098 } // if
[2]1099
[551]1100 if (strmatch)
[948]1101 ret = InsertGrepFile(grep, pszFileName, pffb, pitdSleep, pitdReport);
[2]1102 return ret;
1103}
1104
[1157]1105static LONG cr3tab[] = { // CRC polynomial 0xEDB88320
[2]1106
1107 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
1108 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
1109 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
1110 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
1111 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
1112 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
1113 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
1114 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
1115 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
1116 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
1117 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
1118 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
1119 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
1120 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
1121 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1122 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
1123 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
1124 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
1125 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
1126 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
1127 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
1128 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
1129 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
1130 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
1131 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
1132 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
1133 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
1134 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
1135 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
1136 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1137 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
1138 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
1139 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
1140 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
1141 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
1142 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
1143 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
1144 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
1145 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
1146 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
1147 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
1148 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
1149 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
1150 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
1151 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1152 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
1153 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
1154 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
1155 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
1156 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
1157 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
1158 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
1159 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
1160 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
1161 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
1162 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
1163 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
1164 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
1165 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
1166 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1167 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
1168 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
1169 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
1170 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
1171};
1172
[948]1173LONG CRCBlock(register CHAR *str, register INT blklen, register LONG crc)
[51]1174{
[2]1175 while (blklen--) {
[551]1176 crc =
1177 cr3tab[((INT) crc ^ *str) & 0xff] ^ (((ULONG) crc >> 8) & 0x00FFFFFF);
[2]1178 str++;
1179 }
1180 return crc;
1181}
1182
[948]1183LONG CRCFile(CHAR *pszFileName, INT *error)
[51]1184{
[551]1185 LONG CRC = -1L, len;
[2]1186 FILE *fp;
1187 CHAR *buffer;
[1544]1188 CHAR *moderb = "rb";
[2]1189
1190 *error = 0;
[551]1191 buffer = xmalloc(65535, pszSrcFile, __LINE__);
[350]1192 if (!buffer)
1193 *error = -1;
1194 else {
[1544]1195 fp = xfsopen(pszFileName, moderb, SH_DENYNO, pszSrcFile, __LINE__, TRUE);
[350]1196 if (!fp)
1197 *error = -2;
1198 else {
[551]1199 while (!feof(fp)) {
[1707]1200 len = fread(buffer, 1, 65535, fp);
1201 if (len && len < 65536L)
1202 CRC = CRCBlock(buffer, len, CRC);
1203 else
1204 break;
1205 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
[2]1206 }
1207 fclose(fp);
[1157]1208 // DosSleep(1); // 07 Feb 08 SHL
[2]1209 }
[1039]1210 free(buffer);
[1063]1211# ifdef FORTIFY
1212 Fortify_LeaveScope();
1213# endif
[2]1214 }
1215 return CRC;
1216}
1217
[783]1218static VOID FreeDupes(GREP *grep)
[51]1219{
[551]1220 DUPES *i, *next;
[2]1221
[783]1222 i = grep->dupehead;
[551]1223 while (i) {
[2]1224 next = i->next;
[1032]1225 if (i->name) {
[2]1226 free(i->name);
[1032]1227 }
[2]1228 free(i);
1229 i = next;
1230 }
[783]1231 grep->dupehead = grep->dupelast = NULL;
[1009]1232 xfree(grep->dupenames, pszSrcFile, __LINE__);
1233 xfree(grep->dupesizes, pszSrcFile, __LINE__);
[783]1234 grep->dupesizes = grep->dupenames = NULL;
[1029]1235# ifdef FORTIFY
1236 Fortify_LeaveScope();
[1063]1237# endif
[2]1238}
1239
[948]1240INT comparenamesq(const VOID *v1, const VOID *v2)
[51]1241{
[551]1242 DUPES *d1 = *(DUPES **) v1;
1243 DUPES *d2 = *(DUPES **) v2;
1244 CHAR *p1, *p2;
[2]1245
[551]1246 p1 = strrchr(d1->name, '\\');
1247 if (p1)
[2]1248 p1++;
1249 else
1250 p1 = d1->name;
[551]1251 p2 = strrchr(d2->name, '\\');
1252 if (p2)
[2]1253 p2++;
1254 else
1255 p2 = d2->name;
[551]1256 return stricmp(p1, p2);
[2]1257}
1258
[948]1259INT comparenamesqe(const VOID *v1, const VOID *v2)
[51]1260{
[551]1261 DUPES *d1 = *(DUPES **) v1;
1262 DUPES *d2 = *(DUPES **) v2;
1263 CHAR *p1, *p2, *p1e, *p2e, e1, e2;
[948]1264 INT ret;
[2]1265
[551]1266 p1 = strrchr(d1->name, '\\');
1267 if (p1)
[2]1268 p1++;
1269 else
1270 p1 = d1->name;
[551]1271 p1e = strrchr(p1, '.');
1272 if (p1e) {
[2]1273 e1 = *p1e;
1274 *p1e = 0;
1275 }
[551]1276 p2 = strrchr(d2->name, '\\');
1277 if (p2)
[2]1278 p2++;
1279 else
1280 p2 = d2->name;
[551]1281 p2e = strrchr(p2, '.');
1282 if (p2e) {
[2]1283 e2 = *p2e;
1284 *p2e = 0;
1285 }
[551]1286 ret = stricmp(p1, p2);
1287 if (p1e)
[2]1288 *p1e = e1;
[551]1289 if (p2e)
[2]1290 *p2e = e2;
1291 return ret;
1292}
1293
[948]1294INT comparesizesq(const void *v1, const void *v2)
[51]1295{
[551]1296 DUPES *d1 = *(DUPES **) v1;
1297 DUPES *d2 = *(DUPES **) v2;
[2]1298
1299 return (d1->size > d2->size) ? 1 : (d1->size == d2->size) ? 0 : -1;
1300}
1301
[948]1302INT comparenamesb(const void *v1, const void *v2)
[51]1303{
[551]1304 DUPES *d1 = (DUPES *) v1;
1305 DUPES *d2 = *(DUPES **) v2;
1306 CHAR *p1, *p2;
[2]1307
[551]1308 p1 = strrchr(d1->name, '\\');
1309 if (p1)
[2]1310 p1++;
1311 else
1312 p1 = d1->name;
[551]1313 p2 = strrchr(d2->name, '\\');
1314 if (p2)
[2]1315 p2++;
1316 else
1317 p2 = d2->name;
[551]1318 return stricmp(p1, p2);
[2]1319}
1320
[948]1321INT comparenamesbe(const VOID *v1, const VOID *v2)
[51]1322{
[551]1323 DUPES *d1 = (DUPES *) v1;
1324 DUPES *d2 = *(DUPES **) v2;
1325 CHAR *p1, *p2, *p1e, *p2e, e1, e2;
[948]1326 INT ret;
[2]1327
[551]1328 p1 = strrchr(d1->name, '\\');
1329 if (p1)
[2]1330 p1++;
1331 else
1332 p1 = d1->name;
[551]1333 p1e = strrchr(p1, '.');
1334 if (p1e) {
[2]1335 e1 = *p1e;
1336 *p1e = 0;
1337 }
[551]1338 p2 = strrchr(d2->name, '\\');
1339 if (p2)
[2]1340 p2++;
1341 else
1342 p2 = d2->name;
[551]1343 p2e = strrchr(p2, '.');
1344 if (p2e) {
[2]1345 e2 = *p2e;
1346 *p2e = 0;
1347 }
[551]1348 ret = stricmp(p1, p2);
1349 if (p1e)
[2]1350 *p1e = e1;
[551]1351 if (p2e)
[2]1352 *p2e = e2;
1353 return ret;
1354}
1355
[948]1356INT comparesizesb(const VOID *v1, const VOID *v2)
[51]1357{
[551]1358 DUPES *d1 = (DUPES *) v1;
1359 DUPES *d2 = *(DUPES **) v2;
[2]1360
1361 return (d1->size > d2->size) ? 1 : (d1->size == d2->size) ? 0 : -1;
1362}
1363
[948]1364static VOID FillDupes(GREP *grep,
[1707]1365 ITIMER_DESC *pitdSleep,
1366 ITIMER_DESC *pitdReport)
[51]1367{
[551]1368 DUPES *c, *i, **r;
1369 register CHAR *pc, *pi;
1370 CHAR **list = NULL;
[907]1371 UINT numfiles = 0, numalloced = 0;
1372 INT error;
[948]1373 ULONG x;
1374 ULONG y;
[1157]1375 // ULONG cntr = 1000; // 09 Feb 08 SHL
[2]1376
[1157]1377 // if (grep->CRCdupes) // 09 Feb 08 SHL
1378 // cntr = 100; // 09 Feb 08 SHL
[948]1379 x = 0;
1380 for (i = grep->dupehead; i; i = i->next)
[1157]1381 x++; // Count
[948]1382
[350]1383 if (x) {
[948]1384 if (!hwndStatus)
[1498]1385 WinSetWindowText(grep->hwndCurFile, (CHAR *) GetPString(IDS_GREPDUPESORTINGTEXT));
[948]1386 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
[1498]1387 WinSetWindowText(hwndStatus, (CHAR *) GetPString(IDS_GREPDUPESORTINGTEXT));
[1157]1388 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
[783]1389 grep->dupenames = xmalloc(sizeof(DUPES *) * (x + 1), pszSrcFile, __LINE__);
1390 if (!grep->nosizedupes)
1391 grep->dupesizes = xmalloc(sizeof(DUPES *) * (x + 1), pszSrcFile, __LINE__);
1392 if (grep->dupenames && (grep->nosizedupes || grep->dupesizes)) {
[948]1393 y = 0;
1394 for (i = grep->dupehead; i; i = i->next) {
[1707]1395 grep->dupenames[y] = i;
1396 if (!grep->nosizedupes)
1397 grep->dupesizes[y] = i;
1398 y++;
[2]1399 }
[1157]1400 grep->dupenames[y] = NULL; // Mark end
[783]1401 if (!grep->nosizedupes)
[1707]1402 grep->dupesizes[y] = NULL;
[948]1403
[1157]1404 InitITimer(pitdSleep, 0); // Reset rate estimator
[948]1405 SleepIfNeeded(pitdSleep, 1);
[1157]1406 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
[948]1407
[783]1408 qsort(grep->dupenames,
[1707]1409 x,
1410 sizeof(DUPES *),
1411 grep->ignoreextdupes ? comparenamesqe : comparenamesq);
[948]1412 SleepIfNeeded(pitdSleep, 1);
[1157]1413 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
[783]1414 if (!grep->nosizedupes) {
[1707]1415 qsort(grep->dupesizes, x, sizeof(DUPES *), comparesizesq);
1416 SleepIfNeeded(pitdSleep, 1);
1417 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
[2]1418 }
1419
[948]1420 if (!hwndStatus)
[1707]1421 WinSetWindowText(grep->hwndCurFile, (CHAR *) GetPString(IDS_GREPDUPECOMPARINGTEXT));
[948]1422 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
[1707]1423 WinSetWindowText(hwndStatus, (CHAR *) GetPString(IDS_GREPDUPECOMPARINGTEXT));
[948]1424
[1157]1425 InitITimer(pitdSleep, 0); // Reset rate estimator
[783]1426 i = grep->dupehead;
[766]1427 y = 0;
[551]1428 while (i) {
[1707]1429 if (*grep->stopflag)
1430 break;
1431 SleepIfNeeded(pitdSleep, 1); // 07 Feb 08 SHL
1432 if (!(i->flags & GF_SKIPME)) {
1433 r = (DUPES **) bsearch(i, grep->dupenames, x, sizeof(DUPES *),
1434 ((grep->ignoreextdupes) ? comparenamesbe :
1435 comparenamesb));
1436 if (r) {
1437 while (r > grep->dupenames && ((grep->ignoreextdupes) ?
1438 !comparenamesqe((r - 1), &i) :
1439 !comparenamesq((r - 1), &i)))
1440 r--;
1441 while (*r && ((grep->ignoreextdupes) ?
1442 !comparenamesqe(r, &i) : !comparenamesq(r, &i))) {
1443 if (*r == i || ((*r)->flags & (GF_INSERTED | GF_SKIPME))) {
1444 r++;
1445 continue;
1446 }
1447 if (grep->CRCdupes) {
1448 if ((*r)->CRC == -1L) {
1449 (*r)->CRC = CRCFile((*r)->name, &error);
1450 if (error)
1451 (*r)->CRC = -1L;
1452 else if ((*r)->CRC == -1L)
1453 (*r)->CRC = 0L;
1454 }
1455 if (i->CRC == -1L) {
1456 i->CRC = CRCFile(i->name, &error);
1457 if (error)
1458 i->CRC = -1L;
1459 else if (i->CRC == -1L)
1460 i->CRC = 0L;
1461 }
1462 if (((*r)->size != i->size) || ((*r)->CRC != -1L &&
1463 i->CRC != -1L
1464 && (*r)->CRC != i->CRC)) {
1465 r++;
1466 continue;
1467 }
1468 }
1469 if (!AddToList((*r)->name, &list, &numfiles, &numalloced)) {
1470 (*r)->flags |= GF_INSERTED;
1471 if (grep->sayfiles) {
1472 if (!hwndStatus)
1473 WinSetWindowText(grep->hwndFiles, (*r)->name);
1474 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1475 WinSetWindowText(hwndStatus, (*r)->name);
1476 }
1477 if ((*r)->size == i->size &&
1478 (i->date.year == (*r)->date.year &&
1479 i->date.month == (*r)->date.month &&
1480 i->date.day == (*r)->date.day &&
1481 i->time.hours == (*r)->time.hours &&
1482 i->time.minutes == (*r)->time.minutes &&
1483 i->time.twosecs == (*r)->time.twosecs))
1484 (*r)->flags |= GF_SKIPME;
1485 }
1486 if (!(i->flags & (GF_INSERTED | GF_SKIPME))) {
1487 if (!AddToList(i->name, &list, &numfiles, &numalloced)) {
1488 i->flags |= GF_INSERTED;
1489 if ((*r)->flags & GF_SKIPME)
1490 i->flags |= GF_SKIPME;
1491 }
1492 }
1493 r++;
1494 }
1495 }
1496 if (!grep->nosizedupes) {
1497 r = (DUPES **) bsearch(i,
1498 grep->dupesizes,
1499 x, sizeof(DUPES *), comparesizesb);
1500 if (r) {
1501 while (r > grep->dupesizes && !comparesizesq((r - 1), &i))
1502 r--;
1503 while (*r && !comparesizesq(r, &i)) {
1504 if (*r == i || ((*r)->flags & (GF_INSERTED | GF_SKIPME)) ||
1505 (i->date.year != (*r)->date.year ||
1506 i->date.month != (*r)->date.month ||
1507 i->date.day != (*r)->date.day ||
1508 i->time.hours != (*r)->time.hours ||
1509 i->time.minutes != (*r)->time.minutes ||
1510 i->time.twosecs != (*r)->time.twosecs)) {
1511 r++;
1512 continue;
1513 }
1514 if (grep->CRCdupes) {
1515 if ((*r)->CRC == -1L) {
1516 (*r)->CRC = CRCFile((*r)->name, &error);
1517 if (error)
1518 (*r)->CRC = -1L;
1519 else if ((*r)->CRC == -1L)
1520 (*r)->CRC = 0L;
1521 }
1522 if (i->CRC == -1L) {
1523 i->CRC = CRCFile(i->name, &error);
1524 if (error)
1525 i->CRC = -1L;
1526 else if (i->CRC == -1L)
1527 i->CRC = 0L;
1528 }
1529 if ((*r)->CRC != -1L && i->CRC != -1L &&
1530 (*r)->CRC != i->CRC) {
1531 *r += 1;
1532 continue;
1533 }
1534 }
1535 if (!AddToList((*r)->name, &list, &numfiles, &numalloced)) {
1536 if (grep->sayfiles) {
1537 if (!hwndStatus)
1538 WinSetWindowText(grep->hwndCurFile, (*r)->name);
1539 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1540 WinSetWindowText(hwndStatus, (*r)->name);
1541 }
1542 (*r)->flags |= GF_INSERTED;
1543 if (((grep->ignoreextdupes) ?
1544 comparenamesqe(r, &i) : comparenamesq(r, &i)))
1545 (*r)->flags |= GF_SKIPME;
1546 }
1547 if (!(i->flags & (GF_INSERTED | GF_SKIPME))) {
1548 if (!AddToList(i->name, &list, &numfiles, &numalloced)) {
1549 i->flags |= GF_INSERTED;
1550 if ((*r)->flags & GF_SKIPME)
1551 i->flags |= GF_SKIPME;
1552 }
1553 }
1554 r++;
1555 }
1556 }
1557 }
1558 }
1559 i = i->next;
1560 y++;
1561 // 08 Feb 08 SHL
1562 if (IsITimerExpired(pitdReport)) {
1563 CHAR s[44];
1564 sprintf(s, GetPString(IDS_GREPDUPECHECKPROGTEXT), y, grep->numfiles);
1565 if (!hwndStatus)
1566 WinSetWindowText(grep->hwndCurFile, s);
1567 else {
1568 if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1569 WinSetWindowText(hwndStatus, s);
1570 }
1571 }
[948]1572 } // while
[2]1573 }
1574 else {
[1707]1575 // Insufficient memory - fall back to slow method - FIXME to saymsg?
[1395]1576 if (!fErrorBeepOff)
[1707]1577 DosBeep(50, 100);
[948]1578 if (!hwndStatus)
[1707]1579 WinSetWindowText(grep->hwndCurFile, (CHAR *) GetPString(IDS_GREPDUPECOMPARINGTEXT));
[948]1580 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
[1707]1581 WinSetWindowText(hwndStatus, (CHAR *) GetPString(IDS_GREPDUPECOMPARINGTEXT));
[766]1582 x = y = 0;
[1009]1583 xfree(grep->dupenames, pszSrcFile, __LINE__);
[985]1584 grep->dupenames = NULL;
[1009]1585 xfree(grep->dupesizes, pszSrcFile, __LINE__);
[985]1586 grep->dupesizes = NULL;
[1063]1587# ifdef FORTIFY
1588 Fortify_LeaveScope();
1589# endif
[948]1590
[1157]1591 InitITimer(pitdSleep, 0); // Reset rate estimator
[783]1592 i = grep->dupehead;
[551]1593 while (i) {
[1707]1594 if (*grep->stopflag)
1595 break;
1596 SleepIfNeeded(pitdSleep, 1);
1597 if (!(i->flags & GF_SKIPME)) {
1598 if (IsITimerExpired(pitdReport)) {
1599 // if (!(y % cntr)) { }
1600 CHAR s[44];
1601 sprintf(s, GetPString(IDS_GREPDUPECHECKPROGTEXT), y, grep->numfiles);
1602 if (!hwndStatus)
1603 WinSetWindowText(grep->hwndCurFile, s);
1604 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1605 WinSetWindowText(hwndStatus, s);
1606 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
1607 }
1608 y++;
1609 pi = strrchr(i->name, '\\');
1610 if (pi)
1611 pi++;
1612 else
1613 pi = i->name;
1614 c = grep->dupehead;
1615 while (c) {
1616 if (*grep->stopflag)
1617 break;
1618 if (c != i && !(c->flags & (GF_INSERTED | GF_SKIPME))) {
1619 x++;
1620 pc = strrchr(c->name, '\\');
1621 if (pc)
1622 pc++;
1623 else
1624 pc = c->name;
1625 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
1626 if (grep->CRCdupes) {
1627 if (grep->CRCdupes) {
1628 if (c->CRC == -1L) {
1629 c->CRC = CRCFile(c->name, &error);
1630 if (error)
1631 c->CRC = -1L;
1632 else if (c->CRC == -1L)
1633 c->CRC = 0L;
1634 }
1635 if (i->CRC == -1L) {
1636 i->CRC = CRCFile(i->name, &error);
1637 if (error)
1638 i->CRC = -1L;
1639 else if (i->CRC == -1L)
1640 i->CRC = 0L;
1641 }
1642 if ((c->size != i->size) || (c->CRC != -1L &&
1643 i->CRC != -1L
1644 && c->CRC != i->CRC)) {
1645 c = c->next;
1646 continue;
1647 }
1648 }
1649 }
1650 if (AddToList(c->name, &list, &numfiles, &numalloced))
1651 goto BreakOut; // Failed
1652 if (!(i->flags & GF_INSERTED)) {
1653 if (AddToList(i->name, &list, &numfiles, &numalloced))
1654 goto BreakOut; // Failed
1655 }
1656 if (grep->sayfiles) {
1657 if (!hwndStatus)
1658 WinSetWindowText(grep->hwndCurFile, pc);
1659 else if (WinQueryFocus(HWND_DESKTOP) == grep->hwndFiles)
1660 WinSetWindowText(hwndStatus, pc);
1661 }
1662 c->flags |= GF_INSERTED;
1663 i->flags |= GF_INSERTED;
1664 if (!stricmp(pc, pi)) {
1665 c->flags |= GF_SKIPME;
1666 i->flags |= GF_SKIPME;
1667 }
1668 }
1669 // else if (!(x % 100)) // 07 Feb 08 SHL
1670 // DosSleep(0); //26 Aug 07 GKY 1 // 07 Feb 08 SHL
1671 }
1672 c = c->next;
1673 }
1674 }
1675 i = i->next;
[948]1676 } // while
[2]1677 }
1678 }
1679BreakOut:
[783]1680 FreeDupes(grep);
[551]1681 if (numfiles && list) {
[783]1682 if (!PostMsg(grep->hwndFiles,
[1707]1683 WM_COMMAND,
1684 MPFROM2SHORT(IDM_COLLECTOR, 0),
1685 MPFROMP(list)))
[2]1686 FreeList(list);
1687 }
1688 else
1689 DosPostEventSem(CompactSem);
1690}
1691
[841]1692static BOOL InsertDupe(GREP *grep, CHAR *dir, FILEFINDBUF4L *pffb)
[51]1693{
[2]1694 DUPES *info;
1695
[350]1696 if (*dir) {
[551]1697 info = xmallocz(sizeof(DUPES), pszSrcFile, __LINE__);
[350]1698 if (!info)
1699 return FALSE;
[783]1700
1701 info->name = xstrdup(dir, pszSrcFile, __LINE__);
1702 if (!info->name) {
[1039]1703 free(info);
[1063]1704# ifdef FORTIFY
1705 Fortify_LeaveScope();
1706# endif
[783]1707 return FALSE;
[2]1708 }
[783]1709
1710 info->size = pffb->cbFile;
1711 info->date = pffb->fdateLastWrite;
1712 info->time = pffb->ftimeLastWrite;
1713 info->CRC = -1L;
1714 grep->numfiles++;
1715 if (!grep->dupehead)
1716 grep->dupehead = info;
1717 if (grep->dupelast)
1718 grep->dupelast->next = info;
1719 grep->dupelast = info;
1720 info->next = NULL;
[2]1721 }
1722 return TRUE;
1723}
[783]1724
[948]1725#pragma alloc_text(GREP,InsertGrepFile,DoOneFile,DoInsertion,freegreplist)
[783]1726#pragma alloc_text(GREP,SecsSince1980,match,mmatch,GrepThread)
[948]1727#pragma alloc_text(GREP,DoAllSubdirs,DoMatchingFiles,InsertDupes,FreeDupes)
[783]1728
1729#pragma alloc_text(DUPES,InsertDupe,FillDupes,FreeDupes,CRCFile,CRCBlock)
1730#pragma alloc_text(DUPES,comparenamesq,comparenamesqe,comparenamesb)
1731#pragma alloc_text(DUPES,comparenamesbe,comparesizesq,comparesizesb)
Note: See TracBrowser for help on using the repository browser.