/*********************************************************************** $Id: grep.c 850 2007-10-07 02:50:15Z stevenhl $ grep tools Copyright (c) 1993-98 M. Kimes Copyright (c) 2001, 2007 Steven H. Levine 12 Feb 03 SHL insert_grepfile: standardize EA math 12 Feb 03 SHL doonefile: standardize EA math 25 May 05 SHL Rework for ULONGLONG 25 May 05 SHL Rework for FillInRecordFromFFB 06 Jun 05 SHL Drop unused code 24 Oct 05 SHL dononefile: do not free EA list twice 22 Jul 06 SHL Use Runtime_Error 26 Jul 06 SHL Check more run time errors 19 Oct 06 SHL Correct . and .. detect 03 Nov 06 SHL Count thread usage 03 Aug 07 GKY Enlarged and made setable everywhere Findbuf (speed file loading) 06 Aug 07 GKY Reduce DosSleep times (ticket 148) 13 Aug 07 SHL Avoid pointer errors; sanitize code 13 Aug 07 SHL Move #pragma alloc_text to end for OpenWatcom compat 15 Aug 07 SHL Use FilesToGet directly 26 Aug 07 GKY Improved performance of FillDups 26 Aug 07 GKY DosSleep(1) in loops changed to (0) 21 Sep 07 GKY Fix trap on search that includes filenames that exceed maxpath ***********************************************************************/ #define INCL_DOS #define INCL_WIN #define INCL_DOSERRORS #define INCL_LONGLONG #include #include #include #include #include #include #include "fm3dll.h" #include "fm3str.h" #include "grep.h" #pragma data_seg(DATA2) static PSZ pszSrcFile = __FILE__; static VOID doallsubdirs(GREP *grep, CHAR *searchPath, BOOL recursing, char **fle, int numfls); static INT domatchingfiles(GREP *grep, CHAR *path, char **fle, int numfls); static BOOL doonefile(GREP *grep, CHAR *fileName, FILEFINDBUF4L *pffb); static BOOL doinsertion(GREP *grep); static BOOL InsertDupe(GREP *grep, CHAR *dir, FILEFINDBUF4L *pffb); static VOID FillDupes(GREP *grep); static VOID FreeDupes(GREP *grep); #define GREPCHARS "*?[] \\" #define isleap(year) ((((year%4)==0) && ((year%100)!=0)) || \ ((year%400)==0)) static INT monthdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; ULONG SecsSince1980(FDATE * date, FTIME * time) { ULONG total = 0; register int x; for (x = 1980; x < date->year + 1980; x++) { if (isleap(x)) total += (366 * (24 * 60 * 60)); else total += (365 * (24 * 60 * 60)); } for (x = 1; x < date->month; x++) { if (x == 2 && isleap(date->year + 1980)) total += (29 * (24 * 60 * 60)); else total += ((long)monthdays[x - 1] * (24 * 60 * 60)); } total += (((long)date->day - 1) * (24 * 60 * 60)); total += ((long)time->hours * (60 * 60)); total += ((long)time->minutes * 60); total += ((long)time->twosecs * 2); return total; } /* * this function originally from C_ECHO's Snippets -- modified * brute force methodology */ static BOOL m_match(CHAR * string, CHAR * pattern, BOOL absolute, BOOL ignore, LONG len) { // return TRUE if pattern found in string register CHAR *tn = pattern; register LONG len2 = 0; LONG lastlen = 0; CHAR lo, hi; if (len && string && pattern) { if (absolute) // no pattern matching return (findstring(pattern, strlen(pattern), string, len, (ignore == FALSE)) != NULL); while (*tn && len2 < len) { switch (*tn) { case ' ': while (*tn == ' ') tn++; while (len2 < len && isspace(string[len2])) len2++; break; case '*': while (*tn == '*' || *tn == '?') tn++; if (!*tn) return TRUE; if (ignore) { while (len2 < len && string[len2] != *tn) len2++; } else { while (len2 < len && toupper(string[len2] != *tn)) len2++; } break; case '[': tn++; if (!*tn) return FALSE; lo = *tn; tn++; if (*tn != '-') return FALSE; tn++; if (!*tn) return FALSE; hi = *tn; tn++; if (*tn != ']') return FALSE; tn++; if (ignore) { if ((toupper(string[len2]) >= toupper(lo)) && (toupper(string[len2]) <= toupper(hi))) len2++; else { tn = pattern; len2 = lastlen = lastlen + 1; } } else { if ((string[len2] >= lo) && (string[len2] <= hi)) len2++; else { tn = pattern; len2 = lastlen = lastlen + 1; } } break; case '?': tn++; len2++; break; case '\\': tn++; if (!*tn) return FALSE; // else intentional fallthru default: if (ignore) { if (toupper(*tn) == toupper(string[len2])) { tn++; len2++; } else { tn = pattern; len2 = lastlen = lastlen + 1; } } else { if (*tn == string[len2]) { tn++; len2++; } else { tn = pattern; len2 = lastlen = lastlen + 1; } } break; } } while (*tn == '*') tn++; if (!*tn) return TRUE; } return FALSE; } static BOOL match(CHAR * string, CHAR * patterns, BOOL absolute, BOOL ignore, LONG len, ULONG numlines, CHAR * matched, BOOL matchall) { BOOL ret = FALSE; register CHAR *p; register ULONG x = 0; p = patterns; while (!ret && *p) { ret = m_match(string, p, absolute, ignore, len); if (matchall && ret) break; if (matched && ret && x < numlines) matched[x] = 1; p += strlen(p); // check each pattern in 0-terminated list p++; x++; } return ret; } VOID GrepThread(VOID * arg) { HAB ghab; HMQ ghmq; GREP grep; register INT x, numfls; static CHAR *fle[512]; CHAR *p, *pp, searchPath[CCHMAXPATH * 2]; if (!arg) { Runtime_Error(pszSrcFile, __LINE__, "no data"); return; } grep = *(GREP *)arg; *grep.stopflag = 0; // reset thread-killing flag DosError(FERR_DISABLEHARDERR); priority_normal(); ghab = WinInitialize(0); if (ghab) { grep.ghab = ghab; ghmq = WinCreateMsgQueue(ghab, 0); if (ghmq) { WinCancelShutdown(ghmq, TRUE); IncrThreadUsage(); DosSleep(100); //05 Aug 07 GKY 128 WinSetWindowText(grep.hwndCurFile, GetPString((grep.finddupes) ? IDS_GREPDUPETEXT : IDS_GREPSCANTEXT)); pp = grep.searchPattern; while (*pp) { if (!grep.absFlag) { p = GREPCHARS; // see if any sense in pattern matching while (*p) { if (strchr(pp, *p)) break; p++; } if (!*p) // nope, turn it off grep.absFlag = TRUE; } pp = pp + strlen(pp) + 1; } grep.attrFile &= (~FILE_DIRECTORY); grep.antiattr &= (~FILE_DIRECTORY); if (grep.antiattr & FILE_READONLY) grep.antiattr |= MUST_HAVE_READONLY; if (grep.antiattr & FILE_HIDDEN) grep.antiattr |= MUST_HAVE_HIDDEN; if (grep.antiattr & FILE_SYSTEM) grep.antiattr |= MUST_HAVE_SYSTEM; if (grep.antiattr & FILE_ARCHIVED) grep.antiattr |= MUST_HAVE_ARCHIVED; grep.anyexcludes = FALSE; numfls = x = 0; fle[numfls++] = strtok(grep.tosearch, ";"); while ((fle[numfls] = strtok(NULL, ";")) != NULL && numfls < 511) { if (*fle[numfls] == '/') grep.anyexcludes = TRUE; numfls++; } while (x < numfls) { // loop through search masks if (*fle[x] == '/') // is an exclude mask only goto ExcludeSkip; // first, separate any path from mask p = (char *)(fle[x] + (strlen(fle[x]) - 1)); while (*p != '\\' && *p != ':' && p != fle[x]) --p; if (p == fle[x]) { // no path strcpy(searchPath, grep.curdir); strncpy(grep.fileMask, fle[x], CCHMAXPATH); grep.fileMask[CCHMAXPATH - 1] = 0; } else { // got to deal with a path if (*p == ':') { // just a drive, start in root dir *p = 0; p++; strncpy(searchPath, fle[x], CCHMAXPATH - 2); searchPath[CCHMAXPATH - 3] = 0; strcat(searchPath, ":\\"); strcpy(grep.fileMask, p); } if (*p == '\\') { // got a 'full' path CHAR temp; p++; temp = *p; *p = 0; strncpy(searchPath, fle[x], CCHMAXPATH); searchPath[CCHMAXPATH - 1] = 0; *p = temp; strcpy(grep.fileMask, p); } if (!*grep.fileMask) strcpy(grep.fileMask, "*"); } if (*grep.stopflag) break; // do single directory domatchingfiles(&grep, searchPath, fle, numfls); if (grep.dirFlag) // do subdirs doallsubdirs(&grep, searchPath, FALSE, fle, numfls); ExcludeSkip: if (*grep.stopflag) break; x++; if (WinIsWindow(grep.ghab, grep.hwndFiles)) doinsertion(&grep); // insert any remaining objects } // while if (WinIsWindow(grep.ghab, grep.hwndFiles)) doinsertion(&grep); // insert any remaining objects if (WinIsWindow(grep.ghab, grep.hwndFiles) && grep.finddupes && !*grep.stopflag) FillDupes(&grep); if (!PostMsg(grep.hwndFiles, UM_CONTAINER_FILLED, MPVOID, MPVOID)) // tell window we're done WinSendMsg(grep.hwndFiles, UM_CONTAINER_FILLED, MPVOID, MPVOID); WinDestroyMsgQueue(ghmq); } DecrThreadUsage(); WinTerminate(ghab); } if (!ghmq || !ghab) WinPostMsg(grep.hwndFiles, UM_CONTAINER_FILLED, MPVOID, MPVOID); if (grep.dupehead) FreeDupes(&grep); if (grep.numlines && grep.matched) free(grep.matched); DosPostEventSem(CompactSem); } static BOOL IsExcluded(char *name, char **fle, int numfls) { int x; char *n; n = strrchr(name, '\\'); if (!n) n = strrchr(name, ':'); if (n) n++; else n = name; for (x = 0; x < numfls; x++) { if (*fle[x] == '/' && wildcard((strchr(fle[x], '\\') || strchr(fle[x], ':')) ? name : n, fle[x] + 1, FALSE)) return TRUE; } return FALSE; } static VOID doallsubdirs(GREP * grep, CHAR * searchPath, BOOL recursing, char **fle, int numfls) { // process all subdirectories FILEFINDBUF4 ffb; HDIR findHandle = HDIR_CREATE; LONG ulFindCnt = 1; CHAR *p = NULL; // add a mask to search path if (searchPath[strlen(searchPath) - 1] != '\\') strcat(searchPath, "\\"); strcat(searchPath, "*"); // step through all subdirectories DosError(FERR_DISABLEHARDERR); if (!DosFindFirst(searchPath, &findHandle, (MUST_HAVE_DIRECTORY | FILE_ARCHIVED | FILE_SYSTEM | FILE_HIDDEN | FILE_READONLY), &ffb, (ULONG) sizeof(ffb), (PULONG) & ulFindCnt, FIL_QUERYEASIZE)) { // get rid of mask portion, save end-of-directory p = strrchr(searchPath, '\\'); if (p) p++; else p = searchPath; do { // Process each directory that matches the mask priority_normal(); if (*grep->stopflag) break; // Skip . and .. if (ffb.achName[0] != '.' || (ffb.achName[1] && (ffb.achName[1] != '.' || ffb.achName[2]))) { strcpy(p, ffb.achName); if (!grep->anyexcludes || !IsExcluded(searchPath, fle, numfls)) { domatchingfiles(grep, searchPath, fle, numfls); doallsubdirs(grep, searchPath, TRUE, fle, numfls); DosSleep(0); //26 Aug 07 GKY 1 } } ulFindCnt = 1; } while (!DosFindNext(findHandle, &ffb, sizeof(ffb), (PULONG) & ulFindCnt)); DosFindClose(findHandle); priority_normal(); } if (p) // strip off last directory addition *p = 0; } static INT domatchingfiles(GREP * grep, CHAR * path, char **fle, int numfls) { // process all matching files in a directory PFILEFINDBUF4L pffbArray; PFILEFINDBUF4L pffbFile; ULONG x; HDIR findHandle = HDIR_CREATE; ULONG ulFindCnt; CHAR szFindPath[CCHMAXPATH]; PSZ p; APIRET rc; // 06 Oct 07 SHL Correct size for xDosFindFirst ULONG ulBufBytes = FilesToGet * sizeof(FILEFINDBUF4L); static BOOL fDone; pffbArray = xmalloc(ulBufBytes, pszSrcFile, __LINE__); if (!pffbArray) return 0; // build filemask BldFullPathName(szFindPath, path, grep->fileMask); // sprintf(szFindPath, // "%s%s%s", // path, // (path[strlen(path) - 1] == '\\') ? NullStr : "\\", grep->fileMask); MakeFullName(szFindPath); // find and save end-of-dir position p = strrchr(szFindPath, '\\'); if (p) p++; else p = szFindPath; // step through matching files DosError(FERR_DISABLEHARDERR); ulFindCnt = FilesToGet; rc = xDosFindFirst(szFindPath, &findHandle, FILE_NORMAL | grep->attrFile | grep->antiattr, pffbArray, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZEL); if (!rc) { do { // Process each file that matches the mask priority_normal(); pffbFile = pffbArray; for (x = 0; x < ulFindCnt; x++) { if (*grep->stopflag) break; if (*pffbFile->achName != '.' || (pffbFile->achName[1] && pffbFile->achName[1] != '.')) { strcpy(p, pffbFile->achName); // build filename if (strlen(szFindPath) > CCHMAXPATH){ //21 Sep GKY check for pathnames that exceed maxpath DosFindClose(findHandle); free(pffbArray); if (!fDone) { fDone = TRUE; saymsg(MB_OK | MB_ICONASTERISK, HWND_DESKTOP, GetPString(IDS_WARNINGTEXT), "One or more of your files has a full path name that exceeds the OS/2 maximum"); } return 1; } if (!grep->anyexcludes || !IsExcluded(szFindPath, fle, numfls)) { if (!grep->finddupes) doonefile(grep, szFindPath, pffbFile); else if (!InsertDupe(grep, szFindPath, pffbFile)) { DosFindClose(findHandle); free(pffbArray); return 1; } } } if (!pffbFile->oNextEntryOffset) break; pffbFile = (PFILEFINDBUF4L)((PBYTE)pffbFile + pffbFile->oNextEntryOffset); } // for if (*grep->stopflag) break; DosSleep(0); //26 Aug 07 GKY 1 ulFindCnt = FilesToGet; rc = xDosFindNext(findHandle, pffbArray, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZEL); } while (!rc); DosFindClose(findHandle); priority_normal(); } // if if (rc && rc != ERROR_NO_MORE_FILES) { Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__, GetPString(IDS_CANTFINDDIRTEXT), szFindPath); } free(pffbArray); return 0; } static VOID freegreplist(GREP * grep) { INT x; if (grep) { if (grep->insertffb) { for (x = 0; grep->insertffb[x]; x++) free(grep->insertffb[x]); free(grep->insertffb); } if (grep->dir) { for (x = 0; grep->dir[x]; x++) free(grep->dir[x]); free(grep->dir); } grep->dir = NULL; grep->insertffb = NULL; grep->toinsert = 0L; grep->insertedbytes = 0L; } } static BOOL doinsertion(GREP * grep) { RECORDINSERT ri; DIRCNRDATA *dcd; PCNRITEM pci, pciFirst; INT x; if (!grep || !grep->toinsert || !grep->insertffb || !grep->dir) return FALSE; pci = WinSendMsg(grep->hwndFiles, CM_ALLOCRECORD, MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(grep->toinsert)); if (pci) { if (grep->sayfiles) WinSetWindowText(grep->hwndCurFile, GetPString(IDS_GREPINSERTINGTEXT)); pciFirst = pci; dcd = INSTDATA(grep->hwndFiles); for (x = 0; grep->insertffb[x]; x++) { FillInRecordFromFFB(grep->hwndFiles, pci, grep->dir[x], grep->insertffb[x], FALSE, dcd); pci = (PCNRITEM) pci->rc.preccNextRecord; } memset(&ri, 0, sizeof(RECORDINSERT)); ri.cb = sizeof(RECORDINSERT); ri.pRecordOrder = (PRECORDCORE) CMA_END; ri.pRecordParent = (PRECORDCORE) NULL; ri.zOrder = (USHORT) CMA_TOP; ri.cRecordsInsert = grep->toinsert; ri.fInvalidateRecord = TRUE; WinSendMsg(grep->hwndFiles, CM_INSERTRECORD, MPFROMP(pciFirst), MPFROMP(&ri)); if (dcd) { DosEnterCritSec(); dcd->ullTotalBytes += grep->insertedbytes; DosExitCritSec(); } if (grep->toinsert == FilesToGet) DosSleep(0); //26 Aug 07 GKY 1 freegreplist(grep); PostMsg(grep->hwndFiles, UM_RESCAN, MPVOID, MPVOID); return TRUE; } freegreplist(grep); return FALSE; } static BOOL insert_grepfile(GREP *grep, CHAR *filename, PFILEFINDBUF4L pffb) { PSZ p; CHAR szDirectory[CCHMAXPATH]; if (WinIsWindow(grep->ghab, grep->hwndFiles)) { grep->numfiles++; strcpy(szDirectory, filename); p = strrchr(szDirectory, '\\'); if (p) { if (p < szDirectory + 4) p++; *p = 0; if (!grep->insertffb) { // Allocate 1 extra for end marker? grep->insertffb = xmallocz(sizeof(PFILEFINDBUF4L) * (FilesToGet + 1), pszSrcFile, __LINE__); if (!grep->insertffb) return FALSE; grep->dir = xmallocz(sizeof(CHAR *) * (FilesToGet + 1), pszSrcFile, __LINE__); if (!grep->dir) { free(grep->insertffb); return FALSE; } } grep->insertffb[grep->toinsert] = xmalloc(sizeof(FILEFINDBUF4L), pszSrcFile, __LINE__); if (!grep->insertffb[grep->toinsert]) return FALSE; memcpy(grep->insertffb[grep->toinsert], pffb, sizeof(FILEFINDBUF4L)); grep->dir[grep->toinsert] = xstrdup(szDirectory, pszSrcFile, __LINE__); if (!grep->dir) { free(grep->insertffb[grep->toinsert]); return FALSE; } grep->insertedbytes += pffb->cbFile + CBLIST_TO_EASIZE(pffb->cbList); grep->toinsert++; if (grep->toinsert == FilesToGet) return doinsertion(grep); return TRUE; } } else freegreplist(grep); return FALSE; } static BOOL doonefile(GREP *grep, CHAR *filename, FILEFINDBUF4L * pffb) { // process a single file CHAR *input; FILE *inputFile; ULONG pos; BOOL ret = FALSE, strmatch = FALSE; grep->fileCount++; if (grep->sayfiles) WinSetWindowText(grep->hwndCurFile, filename); if (grep->greaterthan || grep->lessthan) { BOOL keep = TRUE; ULONG adjsize; adjsize = pffb->cbFile + (grep->searchEAs ? CBLIST_TO_EASIZE(pffb->cbList) : 0); if (grep->greaterthan) { if (adjsize < grep->greaterthan) keep = FALSE; } if (keep && grep->lessthan) { if (adjsize > grep->lessthan) keep = FALSE; } if (!keep) return ret; } if (grep->newerthan || grep->olderthan) { BOOL keep = TRUE; ULONG numsecs; numsecs = SecsSince1980(&pffb->fdateLastWrite, &pffb->ftimeLastWrite); if (grep->newerthan) { if (numsecs < grep->newerthan) keep = FALSE; } if (keep && grep->olderthan) { if (numsecs > grep->olderthan) keep = FALSE; } if (!keep) return ret; } if ((!grep->searchEAs && !grep->searchFiles) || !*grep->searchPattern) // just a find return insert_grepfile(grep, filename, pffb); if (grep->searchEAs) { HOLDFEA *head, *info; USHORT type, len; BOOL alltext; CHAR *data, temp; head = GetFileEAs(filename, FALSE, TRUE); if (head) { info = head; while (info && !strmatch) { alltext = TRUE; switch (*(USHORT *) info->value) { case EAT_ASCII: if (match(info->value + (sizeof(USHORT) * 2), grep->searchPattern, grep->absFlag, (grep->caseFlag == FALSE), info->cbValue - (sizeof(USHORT) * 2), grep->numlines, grep->matched, !grep->findifany)) { strmatch = TRUE; } break; case EAT_MVST: type = *(USHORT *) (info->value + (sizeof(USHORT) * 3)); if (type == EAT_ASCII) { data = info->value + (sizeof(USHORT) * 4); len = *(USHORT *) data; data += sizeof(USHORT); while ((data - info->value) + len <= info->cbValue) { temp = *(data + len); *(data + len) = 0; if (match(data, grep->searchPattern, grep->absFlag, (grep->caseFlag == FALSE), len, grep->numlines, grep->matched, !grep->findifany)) { strmatch = TRUE; break; } data += len; if (data - info->value >= info->cbValue) break; *data = temp; len = *(USHORT *) data; data += sizeof(USHORT); } } break; case EAT_MVMT: data = info->value + (sizeof(USHORT) * 3); type = *(USHORT *) data; data += sizeof(USHORT); len = *(USHORT *) data; data += sizeof(USHORT); while ((data - info->value) - len <= info->cbValue) { if (type != EAT_ASCII) { alltext = FALSE; break; } data += len; if (data - info->value >= info->cbValue) break; type = *(USHORT *) data; data += sizeof(USHORT); len = *(USHORT *) data; data += sizeof(USHORT); } if (alltext) { data = info->value + (sizeof(USHORT) * 3); type = *(USHORT *) data; data += sizeof(USHORT); len = *(USHORT *) data; data += sizeof(USHORT); while ((data - info->value) - len <= info->cbValue) { temp = *(data + len); *(data + len) = 0; if (match(data, grep->searchPattern, grep->absFlag, (grep->caseFlag == FALSE), len, grep->numlines, grep->matched, !grep->findifany)) { strmatch = TRUE; break; } data += len; *data = temp; if (data - info->value >= info->cbValue) break; type = *(USHORT *) data; data += sizeof(USHORT); len = *(USHORT *) data; data += sizeof(USHORT); } } break; default: break; } info = info->next; } // while Free_FEAList(head); DosSleep(1); } } if (grep->searchFiles) { input = xmalloc(65537, pszSrcFile, __LINE__); if (input) { LONG len; inputFile = _fsopen(filename, "rb", SH_DENYNO); if (inputFile) { pos = ftell(inputFile); while (!feof(inputFile)) { if (pos) fseek(inputFile, pos - 1024, SEEK_SET); len = fread(input, 1, 65536, inputFile); if (len >= 0) { if (*grep->stopflag) break; if (match(input, grep->searchPattern, grep->absFlag, (grep->caseFlag == FALSE), len, grep->numlines, grep->matched, !grep->findifany)) { strmatch = TRUE; break; } } else break; } fclose(inputFile); } free(input); DosSleep(1); } } // if if (strmatch) ret = insert_grepfile(grep, filename, pffb); return ret; } static LONG cr3tab[] = { // CRC polynomial 0xEDB88320 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; LONG CRCBlock(register CHAR * str, register INT blklen, register LONG crc) { while (blklen--) { crc = cr3tab[((INT) crc ^ *str) & 0xff] ^ (((ULONG) crc >> 8) & 0x00FFFFFF); str++; } return crc; } LONG CRCFile(CHAR * filename, INT * error) { LONG CRC = -1L, len; FILE *fp; CHAR *buffer; *error = 0; buffer = xmalloc(65535, pszSrcFile, __LINE__); if (!buffer) *error = -1; else { fp = _fsopen(filename, "rb", SH_DENYNO); if (!fp) *error = -2; else { while (!feof(fp)) { len = fread(buffer, 1, 65535, fp); if (len && len < 65536L) CRC = CRCBlock(buffer, len, CRC); else break; DosSleep(0); //26 Aug 07 GKY 1 } fclose(fp); DosSleep(1); } free(buffer); } return CRC; } static VOID FreeDupes(GREP *grep) { DUPES *i, *next; i = grep->dupehead; while (i) { next = i->next; if (i->name) free(i->name); free(i); i = next; } grep->dupehead = grep->dupelast = NULL; if (grep->dupenames) free(grep->dupenames); if (grep->dupesizes) free(grep->dupesizes); grep->dupesizes = grep->dupenames = NULL; } int comparenamesq(const void *v1, const void *v2) { DUPES *d1 = *(DUPES **) v1; DUPES *d2 = *(DUPES **) v2; CHAR *p1, *p2; p1 = strrchr(d1->name, '\\'); if (p1) p1++; else p1 = d1->name; p2 = strrchr(d2->name, '\\'); if (p2) p2++; else p2 = d2->name; return stricmp(p1, p2); } int comparenamesqe(const void *v1, const void *v2) { DUPES *d1 = *(DUPES **) v1; DUPES *d2 = *(DUPES **) v2; CHAR *p1, *p2, *p1e, *p2e, e1, e2; int ret; p1 = strrchr(d1->name, '\\'); if (p1) p1++; else p1 = d1->name; p1e = strrchr(p1, '.'); if (p1e) { e1 = *p1e; *p1e = 0; } p2 = strrchr(d2->name, '\\'); if (p2) p2++; else p2 = d2->name; p2e = strrchr(p2, '.'); if (p2e) { e2 = *p2e; *p2e = 0; } ret = stricmp(p1, p2); if (p1e) *p1e = e1; if (p2e) *p2e = e2; return ret; } int comparesizesq(const void *v1, const void *v2) { DUPES *d1 = *(DUPES **) v1; DUPES *d2 = *(DUPES **) v2; return (d1->size > d2->size) ? 1 : (d1->size == d2->size) ? 0 : -1; } int comparenamesb(const void *v1, const void *v2) { DUPES *d1 = (DUPES *) v1; DUPES *d2 = *(DUPES **) v2; CHAR *p1, *p2; p1 = strrchr(d1->name, '\\'); if (p1) p1++; else p1 = d1->name; p2 = strrchr(d2->name, '\\'); if (p2) p2++; else p2 = d2->name; return stricmp(p1, p2); } int comparenamesbe(const void *v1, const void *v2) { DUPES *d1 = (DUPES *) v1; DUPES *d2 = *(DUPES **) v2; CHAR *p1, *p2, *p1e, *p2e, e1, e2; int ret; p1 = strrchr(d1->name, '\\'); if (p1) p1++; else p1 = d1->name; p1e = strrchr(p1, '.'); if (p1e) { e1 = *p1e; *p1e = 0; } p2 = strrchr(d2->name, '\\'); if (p2) p2++; else p2 = d2->name; p2e = strrchr(p2, '.'); if (p2e) { e2 = *p2e; *p2e = 0; } ret = stricmp(p1, p2); if (p1e) *p1e = e1; if (p2e) *p2e = e2; return ret; } int comparesizesb(const void *v1, const void *v2) { DUPES *d1 = (DUPES *) v1; DUPES *d2 = *(DUPES **) v2; return (d1->size > d2->size) ? 1 : (d1->size == d2->size) ? 0 : -1; } static VOID FillDupes(GREP * grep) { DUPES *c, *i, **r; register CHAR *pc, *pi; CHAR **list = NULL; INT numfiles = 0, numalloced = 0, error; register ULONG x = 0, y = 0; ULONG cntr = 1000; if (grep->CRCdupes) cntr = 100; i = grep->dupehead; while (i) { x++; i = i->next; } if (x) { WinSetWindowText(grep->hwndCurFile, GetPString(IDS_GREPDUPESORTINGTEXT)); DosSleep(0); //26 Aug 07 GKY 1 grep->dupenames = xmalloc(sizeof(DUPES *) * (x + 1), pszSrcFile, __LINE__); if (!grep->nosizedupes) grep->dupesizes = xmalloc(sizeof(DUPES *) * (x + 1), pszSrcFile, __LINE__); if (grep->dupenames && (grep->nosizedupes || grep->dupesizes)) { i = grep->dupehead; while (i) { grep->dupenames[y] = i; if (!grep->nosizedupes) grep->dupesizes[y] = i; i = i->next; y++; } grep->dupenames[y] = NULL; if (!grep->nosizedupes) grep->dupesizes[y] = NULL; DosSleep(0); //26 Aug 07 GKY 1 qsort(grep->dupenames, x, sizeof(DUPES *), ((grep->ignoreextdupes) ? comparenamesqe : comparenamesq)); DosSleep(0); //26 Aug 07 GKY 1 if (!grep->nosizedupes) { qsort(grep->dupesizes, x, sizeof(DUPES *), comparesizesq); DosSleep(0); //26 Aug 07 GKY 1 } WinSetWindowText(grep->hwndCurFile, GetPString(IDS_GREPDUPECOMPARINGTEXT)); i = grep->dupehead; y = 0; while (i) { if (*grep->stopflag) break; if (!(i->flags & GF_SKIPME)) { r = (DUPES **) bsearch(i, grep->dupenames, x, sizeof(DUPES *), ((grep->ignoreextdupes) ? comparenamesbe : comparenamesb)); if (r) { while (r > grep->dupenames && ((grep->ignoreextdupes) ? !comparenamesqe((r - 1), &i) : !comparenamesq((r - 1), &i))) r--; while (*r && ((grep->ignoreextdupes) ? !comparenamesqe(r, &i) : !comparenamesq(r, &i))) { if (*r == i || ((*r)->flags & (GF_INSERTED | GF_SKIPME))) { r++; continue; } if (grep->CRCdupes) { if ((*r)->CRC == -1L) { (*r)->CRC = CRCFile((*r)->name, &error); if (error) (*r)->CRC = -1L; else if ((*r)->CRC == -1L) (*r)->CRC = 0L; } if (i->CRC == -1L) { i->CRC = CRCFile(i->name, &error); if (error) i->CRC = -1L; else if (i->CRC == -1L) i->CRC = 0L; } if (((*r)->size != i->size) || ((*r)->CRC != -1L && i->CRC != -1L && (*r)->CRC != i->CRC)) { r++; continue; } } if (!AddToList((*r)->name, &list, &numfiles, &numalloced)) { (*r)->flags |= GF_INSERTED; if (grep->sayfiles) WinSetWindowText(grep->hwndFiles, (*r)->name); if ((*r)->size == i->size && (i->date.year == (*r)->date.year && i->date.month == (*r)->date.month && i->date.day == (*r)->date.day && i->time.hours == (*r)->time.hours && i->time.minutes == (*r)->time.minutes && i->time.twosecs == (*r)->time.twosecs)) (*r)->flags |= GF_SKIPME; } if (!(i->flags & (GF_INSERTED | GF_SKIPME))) { if (!AddToList(i->name, &list, &numfiles, &numalloced)) { i->flags |= GF_INSERTED; if ((*r)->flags & GF_SKIPME) i->flags |= GF_SKIPME; } } r++; } } if (!grep->nosizedupes) { r = (DUPES **) bsearch(i, grep->dupesizes, x, sizeof(DUPES *), comparesizesb); if (r) { while (r > grep->dupesizes && !comparesizesq((r - 1), &i)) r--; while (*r && !comparesizesq(r, &i)) { if (*r == i || ((*r)->flags & (GF_INSERTED | GF_SKIPME)) || (i->date.year != (*r)->date.year || i->date.month != (*r)->date.month || i->date.day != (*r)->date.day || i->time.hours != (*r)->time.hours || i->time.minutes != (*r)->time.minutes || i->time.twosecs != (*r)->time.twosecs)) { r++; continue; } if (grep->CRCdupes) { if ((*r)->CRC == -1L) { (*r)->CRC = CRCFile((*r)->name, &error); if (error) (*r)->CRC = -1L; else if ((*r)->CRC == -1L) (*r)->CRC = 0L; } if (i->CRC == -1L) { i->CRC = CRCFile(i->name, &error); if (error) i->CRC = -1L; else if (i->CRC == -1L) i->CRC = 0L; } if ((*r)->CRC != -1L && i->CRC != -1L && (*r)->CRC != i->CRC) { *r += 1; continue; } } if (!AddToList((*r)->name, &list, &numfiles, &numalloced)) { if (grep->sayfiles) WinSetWindowText(grep->hwndCurFile, (*r)->name); (*r)->flags |= GF_INSERTED; if (((grep->ignoreextdupes) ? comparenamesqe(r, &i) : comparenamesq(r, &i))) (*r)->flags |= GF_SKIPME; } if (!(i->flags & (GF_INSERTED | GF_SKIPME))) { if (!AddToList(i->name, &list, &numfiles, &numalloced)) { i->flags |= GF_INSERTED; if ((*r)->flags & GF_SKIPME) i->flags |= GF_SKIPME; } } r++; } } } } i = i->next; y++; if (!(y % cntr)) { CHAR s[44]; sprintf(s, GetPString(IDS_GREPDUPECHECKPROGTEXT), y, grep->numfiles); WinSetWindowText(grep->hwndCurFile, s); DosSleep(1); //05 Aug 07 GKY 128 } DosSleep(0); //26 Aug 07 GKY 1 } } else { // Insufficient memory - fall back DosBeep(50, 100); WinSetWindowText(grep->hwndCurFile, GetPString(IDS_GREPDUPECOMPARINGTEXT)); x = y = 0; if (grep->dupenames) { free(grep->dupenames); grep->dupenames = NULL; } if (grep->dupesizes) { free(grep->dupesizes); grep->dupesizes = NULL; } i = grep->dupehead; while (i) { if (*grep->stopflag) break; if (!(i->flags & GF_SKIPME)) { if (!(y % cntr)) { CHAR s[44]; sprintf(s, GetPString(IDS_GREPDUPECHECKPROGTEXT), y, grep->numfiles); WinSetWindowText(grep->hwndCurFile, s); DosSleep(0); //26 Aug 07 GKY 1 } y++; pi = strrchr(i->name, '\\'); if (pi) pi++; else pi = i->name; c = grep->dupehead; while (c) { if (*grep->stopflag) break; if (c != i && !(c->flags & (GF_INSERTED | GF_SKIPME))) { x++; pc = strrchr(c->name, '\\'); if (pc) pc++; else pc = c->name; 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 if (grep->CRCdupes) { if (grep->CRCdupes) { if (c->CRC == -1L) { c->CRC = CRCFile(c->name, &error); if (error) c->CRC = -1L; else if (c->CRC == -1L) c->CRC = 0L; } if (i->CRC == -1L) { i->CRC = CRCFile(i->name, &error); if (error) i->CRC = -1L; else if (i->CRC == -1L) i->CRC = 0L; } if ((c->size != i->size) || (c->CRC != -1L && i->CRC != -1L && c->CRC != i->CRC)) { c = c->next; continue; } } } if (AddToList(c->name, &list, &numfiles, &numalloced)) goto BreakOut; // Failed if (!(i->flags & GF_INSERTED)) { if (AddToList(i->name, &list, &numfiles, &numalloced)) goto BreakOut; // Failed } if (grep->sayfiles) WinSetWindowText(grep->hwndCurFile, pc); c->flags |= GF_INSERTED; i->flags |= GF_INSERTED; if (!stricmp(pc, pi)) { c->flags |= GF_SKIPME; i->flags |= GF_SKIPME; } } else if (!(x % 100)) DosSleep(0); //26 Aug 07 GKY 1 } c = c->next; } } i = i->next; } } } BreakOut: FreeDupes(grep); if (numfiles && list) { if (!PostMsg(grep->hwndFiles, WM_COMMAND, MPFROM2SHORT(IDM_COLLECTOR, 0), MPFROMP(list))) FreeList(list); } else DosPostEventSem(CompactSem); } static BOOL InsertDupe(GREP *grep, CHAR *dir, FILEFINDBUF4L *pffb) { DUPES *info; if (*dir) { info = xmallocz(sizeof(DUPES), pszSrcFile, __LINE__); if (!info) return FALSE; info->name = xstrdup(dir, pszSrcFile, __LINE__); if (!info->name) { free(info); return FALSE; } info->size = pffb->cbFile; info->date = pffb->fdateLastWrite; info->time = pffb->ftimeLastWrite; info->CRC = -1L; grep->numfiles++; if (!grep->dupehead) grep->dupehead = info; if (grep->dupelast) grep->dupelast->next = info; grep->dupelast = info; info->next = NULL; } return TRUE; } #pragma alloc_text(GREP,insert_grepfile,doonefile,doinsertion,freegreplist) #pragma alloc_text(GREP,SecsSince1980,match,mmatch,GrepThread) #pragma alloc_text(GREP,doallsubdirs,domatchingfiles,InsertDupes,FreeDupes) #pragma alloc_text(DUPES,InsertDupe,FillDupes,FreeDupes,CRCFile,CRCBlock) #pragma alloc_text(DUPES,comparenamesq,comparenamesqe,comparenamesb) #pragma alloc_text(DUPES,comparenamesbe,comparesizesq,comparesizesb)