APIRET DeleteFile (PSZ pszPath, FILEFINDBUF3 *pFileInfo) { APIRET rc = NO_ERROR; /* API-Returncode */ ULONG ulAgeCurrent; /* canonical file are of current file */ FDATE fdAgeCurrent; /* filedate structure */ FILESTATUS fStat; /* filestatus structure for attributes */ int iAnswer; /* user answer on the confirmation request */ CHAR szFileNameBuffer[MAXPATHLEN]; /* buffer for DosEditName */ FILESTATUS3 fs3; /* filestatus level 3 information from DosQueryPathInfo */ CHAR szFileDate[32]; /* buffer for the file date */ CHAR szFileAttr[6]; /* buffer for the file attributes */ CHAR szTokenizerBuffer[MAXPATHLEN]; /* i hate strtok ! */ if (!Options.fsDontDeleteFiles) /* if we have to remove files */ { /* check for age */ if (Options.fsFileAge) /* deletion selective on file age */ { if (Options.fsFileAgeWrite) { fdAgeCurrent = pFileInfo->fdateLastWrite; ulAgeCurrent = ToolsDateToAge(fdAgeCurrent.day, fdAgeCurrent.month, fdAgeCurrent.year + 1980); } else if (Options.fsFileAgeAccess) { fdAgeCurrent = pFileInfo->fdateLastAccess; ulAgeCurrent = ToolsDateToAge(fdAgeCurrent.day, fdAgeCurrent.month, fdAgeCurrent.year + 1980); } else if (Options.fsFileAgeCreate) { fdAgeCurrent = pFileInfo->fdateCreation; ulAgeCurrent = ToolsDateToAge(fdAgeCurrent.day, fdAgeCurrent.month, fdAgeCurrent.year + 1980); } else { /* none specified, take last-write date */ fdAgeCurrent = pFileInfo->fdateLastWrite; ulAgeCurrent = ToolsDateToAge(fdAgeCurrent.day, fdAgeCurrent.month, fdAgeCurrent.year + 1980); } /* now check if it is to be deleted */ if (Options.fsFileAgeNewer) { if (ulAgeCurrent < Globals.ulFileDate) return (NO_ERROR); /* abort processing for this file */ } else { if (ulAgeCurrent > Globals.ulFileDate) return (NO_ERROR); /* abort processing for this file */ } } /* check with the file name mask */ if (Options.fsFileNameMask) { PSZ pszToken; /* string pointer points to file token within filemask */ BOOL fMatch; /* match - true, no match - false */ strcpy (szTokenizerBuffer, /* strtok is a real PITA !!! */ Options.pszFileNameMask); pszToken = strtok(szTokenizerBuffer, /* tokenize this */ ","); fMatch = FALSE; /* this is the default */ while ( (pszToken != NULL) && /* as long as there is a name to process */ (fMatch == FALSE) ) /* and no match was found */ { rc = DosEditName(1, /* use OS/2 1.2 editing semantics */ pFileInfo->achName, /* source string */ pszToken, /* editing string */ szFileNameBuffer, /* local name buffer */ sizeof (szFileNameBuffer)); /* buffer length */ if (rc != NO_ERROR) /* check for errors */ return (rc); /* raise error condition */ if (stricmp(pFileInfo->achName, /* check if filename has changed */ szFileNameBuffer) == 0) fMatch = TRUE; /* the same, abort processing */ pszToken = strtok(NULL, /* skip to the next token */ ","); } if (fMatch == FALSE) /* no match was found ! */ return (NO_ERROR); /* then go not beyond this point */ } StrFAttrToStringShort (pFileInfo->attrFile, /* map the attributes */ szFileAttr); StrFDateTimeToString (pFileInfo->fdateLastWrite, /* map the date */ pFileInfo->ftimeLastWrite, szFileDate); if (Options.fsSimulation) /* simulate deletion only ? */ printf ("\n %9u %s %s %s", pFileInfo->cbFile, szFileAttr, szFileDate, pFileInfo->achName); else { if (Options.fsVerbose || /* verbose output ? */ Options.fsShowFiles || Options.fsConfirmationPrompt) printf ("\n %9u %s %s %s", pFileInfo->cbFile, szFileAttr, szFileDate, pFileInfo->achName); if (Options.fsConfirmationPrompt) /* prompt for every deletion ? */ { iAnswer = ToolsConfirmationQuery(); /* ask the user */ switch (iAnswer) { case 0: /* no */ return (NO_ERROR); /* abort processing */ case 1: /* yes */ break; /* continue ... */ case 2: /* escape */ exit (1); /* PH: urgs, terminate the process */ } } if (Options.fsForceDelete) rc = DosForceDelete(pszPath); /* file will not be recoverable */ else rc = DosDelete(pszPath); /* OK, remove that thing ! */ if ( (rc == ERROR_ACCESS_DENIED) && /* check for READ-ONLY */ Options.fsRemoveAttributes) { rc = DosQueryPathInfo (pszPath, /* query file information */ FIL_STANDARD, &fStat, sizeof(fStat)); if (rc != NO_ERROR) /* check for errors */ return (rc); /* raise error condition */ fStat.attrFile = FILE_NORMAL; /* reset the attributes */ rc = DosSetPathInfo (pszPath, /* set the information */ FIL_STANDARD, &fStat, sizeof(fStat), 0L); if (rc != NO_ERROR) /* check for errors */ return (rc); /* raise error condition */ /* now try again */ if (Options.fsForceDelete) rc = DosForceDelete(pszPath); /* file will not be recoverable */ else rc = DosDelete(pszPath); /* OK, remove that thing ! */ } } if (rc == NO_ERROR) /* if the file has actually been deleted */ { Globals.ulDeletedBytes += pFileInfo->cbFile; Globals.ulDeletedAlloc += pFileInfo->cbFileAlloc; Globals.ulFilesDeleted++; /* update the statistics */ } } return (rc); /* ok */ }
APIRET ProcessFile (PSZ pszPath, PSZ pszFile) { APIRET rc = NO_ERROR; /* this is an API-returncode */ char szFileName[MAXPATHLEN]; /* local buffer for a modified file name */ char szFileTemp[MAXPATHLEN]; /* local buffer for a modified file name */ FILE *fileInput; /* handle for the input file */ FILE *fileOutput; /* handle for the output file */ char szLineBuffer[4096]; /* 4k buffer for line processing */ if ( (pszPath == NULL) || /* check parameters */ (pszFile == NULL) ) return (ERROR_INVALID_PARAMETER); /* signal error */ if (Options.fFileOutput == TRUE) /* check if output pattern is specified */ { /* first we open all needed files, especially the output file */ rc = DosEditName(1, /* OS/2 1.2 filename semantics apply */ pszFile, /* source pattern */ Options.pszFileOutput, /* modification pattern */ szFileName, /* buffer */ sizeof(szFileName)); /* size of buffer */ if (rc != NO_ERROR) /* check if an error occured */ return (rc); /* signal error */ } else { /* first we open all needed files, especially the output file */ rc = DosEditName(1, /* OS/2 1.2 filename semantics apply */ pszFile, /* source pattern */ "*.NEW", /* modification pattern */ szFileName, /* buffer */ sizeof(szFileName)); /* size of buffer */ if (rc != NO_ERROR) /* check if an error occured */ return (rc); /* signal error */ } strcpy (szFileTemp, /* copy the path information data */ pszPath); strcat (szFileTemp, /* this is the open file name */ pszFile); if (Options.fQuiet != TRUE) /* check if output is appreciated */ printf ("\n[%-34s] -> ",szFileTemp); fileInput = fopen(szFileTemp,"r"); /* open for reading */ if (fileInput == NULL) /* check if opening failed */ return (ERROR_OPEN_FAILED); /* signal error */ strcpy (szFileTemp, /* copy the path information data */ pszPath); strcat (szFileTemp, /* this is the write file name */ szFileName); if (Options.fQuiet != TRUE) /* check if output is appreciated */ printf ("[%-34s]",szFileTemp); /* now open the needed files */ fileOutput = fopen(szFileTemp, "wb"); /* open for writing */ if (fileOutput == NULL) /* check if opening failed */ { fclose(fileInput); /* close the input file handle */ return (ERROR_OPEN_FAILED); /* signal error */ } /* set buffers for input and output */ setvbuf (fileInput, Globals.piobufInput, _IOFBF, IOBUFFERSIZE); setvbuf (fileOutput, Globals.piobufOutput, _IOFBF, IOBUFFERSIZE); if (Globals.pBufferHeader != NULL) /* copy the header file at first */ fwrite(Globals.pBufferHeader, Globals.ulHeaderSize, 1, fileOutput); /* apply the replacement rules linewise */ while (!feof(fileInput)) /* until we reach the end of the input file */ { fgets(szLineBuffer, /* read a new line */ sizeof(szLineBuffer), fileInput); if (feof(fileInput)) /* abort processing here if last line is reached */ break; Globals.ulProcessedLines++; /* correct the statistics */ RulesApply (Globals.pReplacementRoot, /* apply the replacement rules */ szLineBuffer); fwrite(szLineBuffer, /* write the new line to the output file */ strlen(szLineBuffer), 1, fileOutput); } if (Globals.pBufferFooter != NULL) /* append the footer file at last */ fwrite(Globals.pBufferFooter, Globals.ulFooterSize, 1, fileOutput); fclose (fileOutput); /* close the used file handles */ fclose (fileInput); return (rc); /* return code */ }
void scan_attributes (PSZ pszPath, FILEFINDBUF3 *pFileInfo) { char szFileNameBuffer[MAXPATHLEN]; /* buffer for DosEditName */ CHAR szTokenizerBuffer[MAXPATHLEN]; /* i hate strtok ! */ APIRET rc; /* API returncode */ if (Options.fsExcludeDirectories) /* shall dirs be included ? */ if (pFileInfo->attrFile & FILE_DIRECTORY) return; /* check with the file name mask */ if (Options.fsFileNameMask) { PSZ pszToken; /* string pointer points to file token within filemask */ BOOL fMatch; /* match - true, no match - false */ strcpy (szTokenizerBuffer, /* strtok is a real PITA !!! */ Options.pszFileNameMask); pszToken = strtok(szTokenizerBuffer, /* tokenize this */ ","); fMatch = FALSE; /* this is the default */ while ( (pszToken != NULL) && /* as long as there is a name to process */ (fMatch == FALSE) ) /* and no match was found */ { rc = DosEditName(1, /* use OS/2 1.2 editing semantics */ pFileInfo->achName, /* source string */ pszToken, /* editing string */ szFileNameBuffer, /* local name buffer */ sizeof (szFileNameBuffer)); /* buffer length */ if (rc != NO_ERROR) /* check for errors */ return; /* raise error condition */ if (stricmp(pFileInfo->achName, /* check if filename has changed */ szFileNameBuffer) == 0) fMatch = TRUE; /* the same, abort processing */ pszToken = strtok(NULL, /* skip to the next token */ ","); } if (fMatch == FALSE) /* no match was found ! */ return; /* then go not beyond this point */ } sprintf (szFileNameBuffer, "%s\\%s", pszPath, pFileInfo->achName); /*************************************************************************** * display file information * ***************************************************************************/ if (Options.fsFiles2) /* very verbose output */ { StrFAttrToStringShort (pFileInfo->attrFile, /* map the attributes */ Globals.szFileAttr); printf ("\n %s %s", /* attributes and name */ Globals.szFileAttr, szFileNameBuffer); StrFDateTimeToString (pFileInfo->fdateCreation, /* map the date */ pFileInfo->ftimeCreation, Globals.szFileDate); printf ("\n Creation %s, Actual Size %9u", Globals.szFileDate, pFileInfo->cbFile); StrFDateTimeToString (pFileInfo->fdateLastAccess, /* map the date */ pFileInfo->ftimeLastAccess, Globals.szFileDate); printf ("\n Last Access %s, Allocated Size %9u", Globals.szFileDate, pFileInfo->cbFileAlloc); StrFDateTimeToString (pFileInfo->fdateLastWrite, /* map the date */ pFileInfo->ftimeLastWrite, Globals.szFileDate); printf ("\n Last Write %s, Slack space %9i", Globals.szFileDate, pFileInfo->cbFileAlloc - pFileInfo->cbFile); if ( (pFileInfo->cbFileAlloc != 0) && (pFileInfo->cbFileAlloc < pFileInfo->cbFile) ) printf ("\n Compression 1:%2.2f", (float)pFileInfo->cbFile / (float)pFileInfo->cbFileAlloc); } else if (Options.fsFiles) /* if we have to display file information */ { StrFAttrToStringShort (pFileInfo->attrFile, /* map the attributes */ Globals.szFileAttr); StrFDateTimeToString (pFileInfo->fdateLastWrite, /* map the date */ pFileInfo->ftimeLastWrite, Globals.szFileDate); printf ("\n %9u %s %s %s", pFileInfo->cbFile, Globals.szFileAttr, Globals.szFileDate, szFileNameBuffer); } /*************************************************************************** * attribute flags * ***************************************************************************/ if (pFileInfo->cbFileAlloc < pFileInfo->cbFile) Globals.attrCompressed++; if (!pFileInfo->attrFile) Globals.attrNormal++; if (pFileInfo->attrFile & FILE_HIDDEN) Globals.attrHidden++; if (pFileInfo->attrFile & FILE_READONLY) Globals.attrReadonly++; if (pFileInfo->attrFile & FILE_DIRECTORY) Globals.attrDirectory++; if ((pFileInfo->achName[0] == '.') && (( !pFileInfo->achName[1] || ((pFileInfo->achName[1] == '.') && !pFileInfo->achName[2])) )) Globals.attrDirpseudo++; if (pFileInfo->attrFile & FILE_ARCHIVED) Globals.attrArchived++; if (pFileInfo->attrFile & FILE_SYSTEM) Globals.attrSystem++; /* Find undefined attributes */ if (pFileInfo->attrFile & 0xffffffc0) Globals.attrUndefined++; /*************************************************************************** * minimum and maximum compression * ***************************************************************************/ { float fCompressionRate; if ( (pFileInfo->cbFileAlloc != 0) && /* prevent div 0 */ (pFileInfo->cbFileAlloc < pFileInfo->cbFile) ) { fCompressionRate = (float)pFileInfo->cbFile / (float)pFileInfo->cbFileAlloc; Globals.fTotalCompression += fCompressionRate; /* build up the sum */ if ( (fCompressionRate > Globals.fMaximumCompression) || /* maximum */ (Globals.bMaximumCompression == FALSE) ) { Globals.fMaximumCompression = fCompressionRate; Globals.bMaximumCompression = TRUE; strcpy (Globals.pszMaximumCompression, szFileNameBuffer); } if ( (fCompressionRate < Globals.fMinimumCompression) || /* minimum */ (Globals.bMinimumCompression == FALSE) ) { Globals.fMinimumCompression = fCompressionRate; Globals.bMinimumCompression = TRUE; strcpy (Globals.pszMinimumCompression, szFileNameBuffer); } } } /*************************************************************************** * minimum and maximum file and allocation size * ***************************************************************************/ { int iSlackSpace = pFileInfo->cbFileAlloc - pFileInfo->cbFile; if ( (pFileInfo->cbFile > Globals.ulMaximumFileSize) || (Globals.bMaximumFileSize == FALSE) ) { Globals.ulMaximumFileSize = pFileInfo->cbFile; Globals.bMaximumFileSize = TRUE; strcpy (Globals.pszMaximumFileSize, szFileNameBuffer); } if ( (pFileInfo->cbFileAlloc > Globals.ulMaximumAllocationSize) || (Globals.bMaximumAllocationSize == FALSE) ) { Globals.ulMaximumAllocationSize = pFileInfo->cbFileAlloc; Globals.bMaximumAllocationSize = TRUE; strcpy (Globals.pszMaximumAllocationSize, szFileNameBuffer); } if ( (iSlackSpace > Globals.iMaximumSlackSpace) || (Globals.bMaximumSlackSpace == FALSE) ) { Globals.iMaximumSlackSpace = iSlackSpace; Globals.bMaximumSlackSpace = TRUE; strcpy (Globals.pszMaximumSlackSpace, szFileNameBuffer); } if ( (pFileInfo->cbFile < Globals.ulMinimumFileSize) || (Globals.bMinimumFileSize == FALSE) ) { Globals.ulMinimumFileSize = pFileInfo->cbFile; Globals.bMinimumFileSize = TRUE; strcpy (Globals.pszMinimumFileSize, szFileNameBuffer); } if ( (pFileInfo->cbFileAlloc < Globals.ulMinimumAllocationSize) || (Globals.bMinimumAllocationSize == FALSE) ) { Globals.ulMinimumAllocationSize = pFileInfo->cbFileAlloc; Globals.bMinimumAllocationSize = TRUE; strcpy (Globals.pszMinimumAllocationSize, szFileNameBuffer); } if ( (iSlackSpace < Globals.iMinimumSlackSpace) || (Globals.bMinimumSlackSpace == FALSE) ) { Globals.iMinimumSlackSpace = iSlackSpace; Globals.bMinimumSlackSpace = TRUE; strcpy (Globals.pszMinimumSlackSpace, szFileNameBuffer); } } /*************************************************************************** * maximum file dates (most recent files) * ***************************************************************************/ { Globals.fTotalAgeCreation += (float)ToolsDateToAge(pFileInfo->fdateCreation.day, pFileInfo->fdateCreation.month, pFileInfo->fdateCreation.year + 1980) - Globals.fTotalAgeCurrent; Globals.fTotalAgeLastWrite += (float)ToolsDateToAge(pFileInfo->fdateLastWrite.day, pFileInfo->fdateLastWrite.month, pFileInfo->fdateLastWrite.year + 1980) - Globals.fTotalAgeCurrent; Globals.fTotalAgeLastAccess += (float)ToolsDateToAge(pFileInfo->fdateLastAccess.day, pFileInfo->fdateLastAccess.month, pFileInfo->fdateLastAccess.year + 1980) - Globals.fTotalAgeCurrent; if ( (ToolsDateCompare(pFileInfo->fdateCreation, pFileInfo->ftimeCreation, Globals.fdateMaximumCreation, Globals.ftimeMaximumCreation) > 0 ) || (Globals.bMaximumCreation == FALSE) ) { Globals.fdateMaximumCreation = pFileInfo->fdateCreation; Globals.ftimeMaximumCreation = pFileInfo->ftimeCreation; Globals.bMaximumCreation = TRUE; strcpy (Globals.pszMaximumCreation, szFileNameBuffer); } if ( (ToolsDateCompare(pFileInfo->fdateLastAccess, pFileInfo->ftimeLastAccess, Globals.fdateMaximumLastAccess, Globals.ftimeMaximumLastAccess) > 0 ) || (Globals.bMaximumLastAccess == FALSE) ) { Globals.fdateMaximumLastAccess = pFileInfo->fdateLastAccess; Globals.ftimeMaximumLastAccess = pFileInfo->ftimeLastAccess; Globals.bMaximumLastAccess = TRUE; strcpy (Globals.pszMaximumLastAccess, szFileNameBuffer); } if ( (ToolsDateCompare(pFileInfo->fdateLastWrite, pFileInfo->ftimeLastWrite, Globals.fdateMaximumLastWrite, Globals.ftimeMaximumLastWrite) > 0 ) || (Globals.bMaximumLastWrite == FALSE) ) { Globals.fdateMaximumLastWrite = pFileInfo->fdateLastWrite; Globals.ftimeMaximumLastWrite = pFileInfo->ftimeLastWrite; Globals.bMaximumLastWrite = TRUE; strcpy (Globals.pszMaximumLastWrite, szFileNameBuffer); } } /*************************************************************************** * minimum file dates (oldest files) * ***************************************************************************/ { if ( (ToolsDateCompare(pFileInfo->fdateCreation, pFileInfo->ftimeCreation, Globals.fdateMinimumCreation, Globals.ftimeMinimumCreation) < 0 ) || (Globals.bMinimumCreation == FALSE) ) { Globals.fdateMinimumCreation = pFileInfo->fdateCreation; Globals.ftimeMinimumCreation = pFileInfo->ftimeCreation; Globals.bMinimumCreation = TRUE; strcpy (Globals.pszMinimumCreation, szFileNameBuffer); } if ( (ToolsDateCompare(pFileInfo->fdateLastAccess, pFileInfo->ftimeLastAccess, Globals.fdateMinimumLastAccess, Globals.ftimeMinimumLastAccess) < 0 ) || (Globals.bMinimumLastAccess == FALSE) ) { Globals.fdateMinimumLastAccess = pFileInfo->fdateLastAccess; Globals.ftimeMinimumLastAccess = pFileInfo->ftimeLastAccess; Globals.bMinimumLastAccess = TRUE; strcpy (Globals.pszMinimumLastAccess, szFileNameBuffer); } if ( (ToolsDateCompare(pFileInfo->fdateLastWrite, pFileInfo->ftimeLastWrite, Globals.fdateMinimumLastWrite, Globals.ftimeMinimumLastWrite) < 0 ) || (Globals.bMinimumLastWrite == FALSE) ) { Globals.fdateMinimumLastWrite = pFileInfo->fdateLastWrite; Globals.ftimeMinimumLastWrite = pFileInfo->ftimeLastWrite; Globals.bMinimumLastWrite = TRUE; strcpy (Globals.pszMinimumLastWrite, szFileNameBuffer); } } }
/** * Processes a single file. * @returns 0 if successfully processed. * -2 if wrong format. * other error code on failure. * @param pszFile Name of the file to process. * @param pszFilePattern File pattern to match pszFile with. * @author knut st. osmundsen ([email protected]) */ int ProcessFile(const char *pszFile1, unsigned long cbFile1, const char *pszFilePattern) { int rc = 0; FILESTATUS3 fst3; int cchPattern = strlen(pszFilePattern); char szFile2[CCHMAXPATH]; char szPattern[CCHMAXPATH]; const char * pszFileName; const char * pszPatternName; /* * Correct the pattern. */ memcpy(szPattern, pszFilePattern, cchPattern+1); if (szPattern[cchPattern - 1] == '\\' || szPattern[cchPattern - 1] == '/') szPattern[cchPattern++] = '*'; else { if (!DosQueryPathInfo((PSZ)pszFilePattern, FIL_STANDARD, &fst3, sizeof(fst3))) { if (fst3.attrFile & FILE_DIRECTORY) { szPattern[cchPattern++] = '\\'; szPattern[cchPattern++] = '*'; } } } szPattern[cchPattern] = '\0'; /* * Get the filename part of pszFile1. */ pszFileName = strrchr(pszFile1, '\\'); if (!pszFileName) pszFileName = strrchr(pszFile1, '/'); if (!pszFileName) pszFileName = strchr(pszFile1, ':'); if (!pszFileName) pszFileName = pszFile1 - 1; pszFileName++; /* * Get the filename portion of szPattern. */ pszPatternName = strrchr(szPattern, '\\'); if (!pszPatternName) pszPatternName = strrchr(szPattern, '/'); if (!pszPatternName) pszPatternName = strchr(szPattern, ':'); if (!pszPatternName) pszPatternName = szPattern - 1; pszPatternName++; /* * Edit the input name according to the pattern. */ rc = DosEditName(1, (PSZ)pszFileName, (PSZ)pszPatternName, szFile2, sizeof(szFile2)); if (!rc) { /* * Make fully qualified name. */ if (pszPatternName == szPattern) { memmove(szFile2 + (int)pszFileName - (int)pszFile1, szFile2, strlen(szFile2) + 1); memcpy(szFile2, pszFile1, (int)pszFileName - (int)pszFile1); } else { memmove(szFile2 + (int)pszPatternName - (int)szPattern, szFile2, strlen(szFile2) + 1); memcpy(szFile2, szPattern, (int)pszPatternName - (int)szPattern); } /* * Check for existance of target. */ rc = DosQueryPathInfo(szFile2, FIL_STANDARD, &fst3, sizeof(fst3)); if (rc == NO_ERROR && !(fst3.attrFile & FILE_DIRECTORY)) { ULONG ulAction = 0; ULONG cbFile2 = fst3.cbFile; HFILE hFile1 = NULLHANDLE; HFILE hFile2 = NULLHANDLE; rc = DosOpen(szFile2, &hFile2, &ulAction, 0, FILE_NORMAL, OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS, OPEN_FLAGS_SEQUENTIAL | OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, NULL); if (!rc) { ulAction = 0; rc = DosOpen((PSZ)pszFile1, &hFile1, &ulAction, 0, FILE_NORMAL, OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS, OPEN_FLAGS_SEQUENTIAL | OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, NULL); if (!rc) { unsigned long cMismatches = 0; unsigned long offRead = 0; while (cbFile1 > 0 && cbFile2 > 0) { static char szBuffer1[0x10000]; static char szBuffer2[0x10000]; ULONG cbRead1; ULONG cbRead2; APIRET rc1; APIRET rc2; rc1 = DosRead(hFile1, &szBuffer1[0], min(sizeof(szBuffer1), cbFile1), &cbRead1); cbFile1 -= cbRead1; rc2 = DosRead(hFile2, &szBuffer2[0], min(sizeof(szBuffer2), cbFile2), &cbRead2); cbFile2 -= cbRead2; if (!rc1 && !rc2) { int cbCmp = min(cbRead1, cbRead2); /* * Check if equal using fast compare. */ if (memcmp(&szBuffer1[0], &szBuffer2[0], cbCmp)) { int i; /* * Wasn't equal. Display mismatches using slow byte by byte compare. */ for (i = 0; i < cbCmp; i++) { if (szBuffer1[i] != szBuffer2[i]) { if (!options.fQuiet) { if (cMismatches++ == 0) printf("Mismatch comparing '%s' and '%s'.\n", pszFile1, szFile2); printf("at 0x%08x 0x%02x (%c) != 0x%02 (%c)\n", offRead + i, szBuffer1[i], isprint(szBuffer1[i]) ? szBuffer1[i] : ' ', szBuffer2[i], isprint(szBuffer2[i]) ? szBuffer2[i] : ' '); } else cMismatches++; } } } /* * Check if last read and size is different. */ if (cbRead1 != cbRead2) { if (!options.fQuiet) { if (cMismatches == 0) printf("Mismatch comparing '%s' and '%s'.\n", pszFile1, szFile2); printf("Length differs. %d != %d\n", offRead + cbRead1 + cbFile1, offRead + cbRead2 + cbFile2); printf("%d differences so far\n", cMismatches); } rc = 1; break; } /* * Last read? */ if (!cbFile1 || !cbFile2) { if (!options.fQuiet) { if (cMismatches > 0) { if (cMismatches == 0) printf("Mismatch comparing '%s' and '%s'.\n", pszFile1, szFile2); printf("%d differences\n", cMismatches); } else printf("Successfull. '%s' matches '%s'.\n", pszFile1, szFile2); } } } else { /* * Read Error. */ if (rc1) printf("Error: failed to read from '%s'. rc=%d\n", pszFile1, rc1); if (rc2) printf("Error: failed to read from '%s'. rc=%d\n", szFile2, rc2); rc = rc1 ? rc1 : rc2; break; } } DosClose(hFile1); /* * Return number of errors. */ if (cMismatches && !rc) rc = cMismatches; } else fprintf(stderr, "(SYS%04d): Could not open file '%s'.\n", rc, pszFile1); DosClose(hFile2); } else fprintf(stderr, "(SYS%04d): Could not open file '%s'.\n", rc, szFile2); } else { if (rc) fprintf(stderr, "(SYS%04d): File '%s' was not found.\n", rc, szFile2); else fprintf(stderr, "Error: Can't compare a file with a directory (%s).\n", szFile2); } } else fprintf(stderr, "Internal error DosEditName(1, '%s','%s',..) -> rc=%d\n", pszFileName, pszPatternName, rc); return rc; }