// sortlog.c // // this program sorts memsnap and poolsnap logs into a more readable form // sorts by pid // scans the data file one time, inserts record offsets based on PID into linked list // then writes data into new file in sorted order // determine whether we have a poolsnap or memsnap log - in pid is equivalent // to pooltag for our sorting #include #include #include #include #include // definitions #define RECSIZE 1024 // record size (max line size) #define MAXTAGSIZE 200 // max length of tag name #define DEFAULT_INFILE "memsnap.log" #define DEFAULT_OUTFILE "memsort.log" typedef enum _FILE_LOG_TYPES { MEMSNAPLOG=0, POOLSNAPLOG, UNKNOWNLOG } FILE_LOG_TYPES; // // Linked list of unique PID or PoolTag // typedef struct PIDList { char PIDItem[11]; struct RecList* RecordList; struct PIDList* Next; DWORD Count; // number of items pointed to by RecordList }; // // For each PID or pool tag, we have a linked list of offsets into file of each line // typedef struct RecList { LONG rOffset; struct RecList* Next; }; // global data FILE_LOG_TYPES CurrentFileType= UNKNOWNLOG; CHAR szHeader[RECSIZE]; // first line of file BOOL bIgnoreTransients= FALSE; // Ignore tags or processes that aren't in every snapshot DWORD g_MaxSnapShots= 0; // max snap shots in the file #define INVALIDOFFSET (-2) /* invalid file offset */ // prototypes VOID ScanFile(FILE *, struct PIDList *); VOID WriteFilex(FILE *, FILE *, struct PIDList *); VOID Usage(VOID) { printf("sortlog [-?] [] []\n"); printf("Sorts an outputfile from memsnap.exe/poolsnap.exe in PID/PoolTag order\n"); printf("-? prints this help\n"); printf("-i ignore tags or processes that are not in every snapshot\n"); printf(" = %s by default\n",DEFAULT_INFILE ); printf(" = %s by default\n",DEFAULT_OUTFILE); exit(-1); } // CheckPointer // // Make sure it is not NULL. Otherwise print error message and exit. // VOID CheckPointer( PVOID ptr ) { if( ptr == NULL ) { printf("Out of memory\n"); exit(-1); } } #include "tags.c" int __cdecl main(int argc, char* argv[]) { FILE* InFile; FILE* OutFile; struct PIDList ThePIDList = {0}; CHAR* pszInFile= NULL; // input filename CHAR* pszOutFile= NULL; // output filename INT iFileIndex= 0; INT iCmdIndex; // index into argv ThePIDList.RecordList = (struct RecList *)LocalAlloc(LPTR, sizeof(struct RecList)); CheckPointer( ThePIDList.RecordList ); ThePIDList.RecordList->rOffset= INVALIDOFFSET; // // parse command line // for( iCmdIndex=1; iCmdIndexNext != 0 ) { int iComp; iComp= strcmp( PID, TmpPIDList->PIDItem); if( iComp == 0 ) { // found Found= TRUE; break; } else { // not found if( iComp < 0 ) { // exit if we have gone far enough break; } TmpPIDList= TmpPIDList->Next; } } // if matching, append offset to RecordList // add offset to current PID list if( Found ) { TmpPIDList->Count= TmpPIDList->Count + 1; if( TmpPIDList->Count > g_MaxSnapShots ) g_MaxSnapShots= TmpPIDList->Count; TmpRecordList= TmpPIDList->RecordList; // walk to end of list while( TmpRecordList->Next != 0 ) { TmpRecordList= TmpRecordList->Next; } TmpRecordList->Next= (struct RecList*)LocalAlloc(LPTR, sizeof(struct RecList)); CheckPointer( TmpRecordList->Next ); TmpRecordList->Next->rOffset= Offset; } // make new PID list, add new PID, add offset else { struct PIDList* pNewPID; // allocate a new PID, // copy current PID information to it // overwrite current PID information with new PID information // have current PID point to new PID which may point on pNewPID= (struct PIDList*) LocalAlloc(LPTR, sizeof(struct PIDList)); CheckPointer( pNewPID ); memcpy( pNewPID, TmpPIDList, sizeof(*pNewPID) ); strcpy( TmpPIDList->PIDItem, PID ); TmpPIDList->RecordList= (struct RecList*) LocalAlloc(LPTR, sizeof(struct RecList)); CheckPointer( TmpPIDList->RecordList ); TmpPIDList->RecordList->rOffset= Offset; TmpPIDList->Next= pNewPID; TmpPIDList->Count= 1; } /* if EOF, return */ /* clear the inBuff */ inBuff[0] = 0; } } // look for the next PID line in the first table VOID WriteFilex(FILE *InFile, FILE *OutFile, struct PIDList *ThePIDList) { struct PIDList *TmpPIDList; struct RecList *TmpRecordList; char inBuff[RECSIZE] = {0}; /* initialize temp list pointer */ TmpPIDList = ThePIDList; /* heading */ fprintf(OutFile,"%s\n",szHeader); OutputTags( OutFile ); /* while not end of list, write records at offset to end of output file */ while (TmpPIDList != 0) { TmpRecordList = TmpPIDList->RecordList; if( (!bIgnoreTransients) || (TmpPIDList->Count == g_MaxSnapShots) ) { while (TmpRecordList != 0) { LONG Offset; Offset= TmpRecordList->rOffset; if( Offset != INVALIDOFFSET ) { /* read in record */ if (fseek(InFile, TmpRecordList->rOffset, SEEK_SET) == -1) break; if (fscanf(InFile, "%[^\n]", &inBuff) != 1) break; /* read out record */ fprintf(OutFile, "%s\n", &inBuff); } /* get next record */ TmpRecordList = TmpRecordList->Next; } /* add a line here */ fputc('\n', OutFile); } /* get next record */ TmpPIDList = TmpPIDList->Next; } }