961 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			961 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* log4res.c   (c)Copyright Sequiter Software Inc., 1988-1996.  All rights reserved. */
 | |
| /* Applies a backedup .LOG file to DBF's */
 | |
| 
 | |
| /****************************************************************************
 | |
| **::  Preprocessor Directives
 | |
| ****************************************************************************/
 | |
| 
 | |
| #include "d4all.h"
 | |
| 
 | |
| #ifndef S4UTILS
 | |
|    #error - Must compile with S4UTILS defined
 | |
| #endif
 | |
| 
 | |
| #include "u4trans.h"
 | |
| /*#include <sys\stat.h>*/
 | |
| 
 | |
| #ifndef S4WINDOWS
 | |
| #ifndef S4UNIX
 | |
|    #ifdef __TURBOC__
 | |
|       #pragma hdrstop
 | |
|    #endif
 | |
|    extern unsigned _stklen = 10000;
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| #ifdef S4DLL_BUILD
 | |
|    extern FILE *stdout, *stderr ;
 | |
|    extern unsigned int messageType ;
 | |
|    HWND hWndStatus ;  /* status window handle */
 | |
| #endif
 | |
| 
 | |
| #define FILENAMELEN  12
 | |
| 
 | |
| #define UTIL4ADD       0
 | |
| #define UTIL4ALL       1
 | |
| #define UTIL4EXCLUSIVE 2
 | |
| #define UTIL4INDEX     3
 | |
| #define UTIL4LOG       4
 | |
| #define UTIL4REMOVE    5
 | |
| 
 | |
| /****************************************************************************
 | |
| **::  Global scope types and variables
 | |
| ****************************************************************************/
 | |
| 
 | |
| static UTIL4FLAG u4flags[] =
 | |
| {
 | |
|    { "ADd",       0, 2, 2, 2, 0, 0, 0, 0, "[-add <target.dbf> [<destination.dbf>]]\r\n" },
 | |
|    { "ALl",       0, 2, 1, 1, 1, 0, 0, 0, "[-all {OFF | ON}]\r\n"                       },
 | |
|    { "Exclusive", 0, 1, 1, 1, 1, 0, 0, 0, "[-exclusive {OFF | ON}]\r\n"                 },
 | |
|    { "Index",     0, 1, 1, 1, 1, 0, 0, 0, "[-index {OFF | ON}]\r\n"                     },
 | |
|    { "Log",       0, 1, 1, 1, 1, 0, 0, 0, "{-log <backup.log>}\r\n"                     },
 | |
|    { "Remove",    0, 1, 2, 1, 1, 0, 0, 0, "[-remove <target.dbf>]\r\n"                  },
 | |
| };
 | |
| 
 | |
| static int u4flagsNum = 6;
 | |
| 
 | |
| static FIELD4INFO openFields[] =
 | |
| {
 | |
|    { "CLIENTID",   'N', 11, 0 },
 | |
|    { "SERVERDTID", 'N', 11, 0 },
 | |
|    { "DATA4PTR",   'N', 11, 0 },
 | |
|    { 0,0,0,0 },
 | |
| };
 | |
| 
 | |
| static TAG4INFO openTags[] =
 | |
| {
 | |
|    { "CLID", "STR(CLIENTID,11,0)+STR(SERVERDTID,11,0)", ".NOT.DELETED()", r4unique, 0 },
 | |
|    { 0,0,0,0,0 },
 | |
| };
 | |
| 
 | |
| static FIELD4INFO tranFields[] =
 | |
| {
 | |
|    { "TRANID", 'N', 11, 0 },  /* rolledback transaction ids */
 | |
|    { 0,0,0,0 },
 | |
| };
 | |
| 
 | |
| static TAG4INFO tranTags[] =
 | |
| {
 | |
|    { "TRANID", "STR(TRANID,11,0)", ".NOT.DELETED()", r4unique, 0 },
 | |
|    { 0,0,0,0,0 },
 | |
| };
 | |
| 
 | |
| #ifndef S4WINDOWS
 | |
|    char *statusStringBlank = "                         ";
 | |
|    char *statusStringMessg = "Processing log file: ";
 | |
|    char *statusStringBckSp = "\r";
 | |
|    char *statusStringFormt = "%3d.%02d%%%%";
 | |
|    #ifdef S4UNIX
 | |
|       char statusStringSpace[10];
 | |
|    #else
 | |
|       char *statusStringSpace = "100.00  ";
 | |
|    #endif
 | |
| #else
 | |
|    extern char *statusStringBlank ;
 | |
|    extern char *statusStringMessg ;
 | |
|    extern char *statusStringBckSp ;
 | |
|    extern char *statusStringFormt ;
 | |
|    extern char *statusStringSpace ;
 | |
| #endif
 | |
| 
 | |
| /*::************************************************************************/
 | |
| 
 | |
| /****************************************************************************
 | |
| **::  Function: typeTran4Open
 | |
| **
 | |
| *****************************************************************************
 | |
| **
 | |
| **    Function: typeTran4Open()
 | |
| **
 | |
| ****************************************************************************/
 | |
| static short typeTran4Open(CODE4 *c4, UTIL4FLAG u4flags[], int u4flagsNum, DATA4 *openDbfs, TRAN4 *t4, int all)
 | |
| {
 | |
|    DATA4 *tempDbf=0;
 | |
|    short rc, found, logNumFields;
 | |
|    unsigned i;
 | |
|    char *data, *fullName, fileName[FILENAMELEN+1], addName[LEN4PATH+1], *destName=0, *cmpName;
 | |
|    char *outMess[4], *logDbfDate;
 | |
|    long logRecordWidth, logNumRecords, logDbfTime;
 | |
| /* struct _stat statbuf;    */
 | |
| 
 | |
|    data = (char *)tran4getData(t4, 0L);
 | |
|    if (data == 0)
 | |
|       return(-1);
 | |
|    fullName = (char *)u4allocFree(c4, *(short *)data+1);
 | |
|    if (fullName == 0)
 | |
|       return(-1);
 | |
|    strncpy(fullName, data+2, *(short *)data);
 | |
|    fullName[*(short *)data] = 0;
 | |
| 
 | |
|    if (all == 0)
 | |
|    {
 | |
|       found = 0;
 | |
|       for (i=0; i<u4flags[UTIL4ADD].numPtr/4; i++)
 | |
|       {
 | |
|          u4namePiece(fileName, FILENAMELEN+1, u4flags[UTIL4ADD].ptr[i]+1, 0, 1);
 | |
|          if (strlen(fileName) != strlen(u4flags[UTIL4ADD].ptr[i]+1))
 | |
|          {
 | |
|             u4nameCurrent(addName, LEN4PATH+1, u4flags[UTIL4ADD].ptr[i]+1);
 | |
|             #ifdef S4UNIX
 | |
|                u4nameExt(addName, LEN4PATH+1, ".dbf", 0);
 | |
|             #else
 | |
|                u4nameExt(addName, LEN4PATH+1, ".DBF", 0);
 | |
|             #endif
 | |
|             cmpName = fullName;
 | |
|          }
 | |
|          else
 | |
|          {
 | |
|             u4namePiece(addName, LEN4PATH+1, fullName, 0, 1);
 | |
|             #ifdef S4UNIX
 | |
|                u4nameExt(fileName, LEN4PATH+1, ".dbf", 0);
 | |
|             #else
 | |
|                u4nameExt(fileName, LEN4PATH+1, ".DBF", 0);
 | |
|             #endif
 | |
|             cmpName = fileName;
 | |
|          }
 | |
|          if (i != u4flags[UTIL4ADD].numPtr/4-1 && *u4flags[UTIL4ADD].ptr[i] == *u4flags[UTIL4ADD].ptr[i+1])
 | |
|             destName = u4flags[UTIL4ADD].ptr[++i]+1;
 | |
|          if (strcmp(addName, cmpName) == 0)
 | |
|          {
 | |
|             found = 1;
 | |
|             break;
 | |
|          }
 | |
|          destName = 0;
 | |
|       }
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       found = 1;
 | |
|       for (i=0; i<u4flags[UTIL4REMOVE].numPtr/4; i++)
 | |
|       {
 | |
|          u4namePiece(fileName, FILENAMELEN+1, u4flags[UTIL4REMOVE].ptr[i], 0, 1);
 | |
|          if (strlen(fileName) != strlen(u4flags[UTIL4REMOVE].ptr[i]))
 | |
|          {
 | |
|             u4nameCurrent(addName, LEN4PATH+1, u4flags[UTIL4REMOVE].ptr[i]);
 | |
|             #ifdef S4UNIX
 | |
|                u4nameExt(addName, LEN4PATH+1, ".dbf", 0);
 | |
|             #else
 | |
|                u4nameExt(addName, LEN4PATH+1, ".DBF", 0);
 | |
|             #endif
 | |
|             cmpName = fullName;
 | |
|          }
 | |
|          else
 | |
|          {
 | |
|             u4namePiece(addName, LEN4PATH+1, fullName, 0, 1);
 | |
|             #ifdef S4UNIX
 | |
|                u4nameExt(fileName, LEN4PATH+1, ".dbf", 0);
 | |
|             #else
 | |
|                u4nameExt(fileName, LEN4PATH+1, ".DBF", 0);
 | |
|             #endif
 | |
|             cmpName = fileName;
 | |
|          }
 | |
|          if (strcmp(addName, cmpName) == 0)
 | |
|          {
 | |
|             found = 0;
 | |
|             break;
 | |
|          }
 | |
|       }
 | |
|    }
 | |
|    strcpy(addName, fullName);
 | |
|    u4free(fullName);
 | |
|    if (found == 0)
 | |
|       return(0);
 | |
| 
 | |
|    #ifdef S4DATA_ALIGN
 | |
|       memcpy(&logRecordWidth, (data+2+*(short *)data), sizeof(long) );
 | |
|       memcpy(&logNumFields, (data+6+*(short *)data), sizeof(short) );
 | |
|       memcpy(&logNumRecords, (data+8+*(short *)data), sizeof(long) );
 | |
|       memcpy(&logDbfTime, (data+12+*(short *)data), sizeof(long) );
 | |
|    #else
 | |
|       logRecordWidth = *(long *)(data+2+ *(short *)data);
 | |
|       logNumFields = *(short *)(data+6+ *(short *)data);
 | |
|       logNumRecords = *(long *)(data+8+ *(short *)data);
 | |
|       logDbfTime = *(long *)(data+12+*(short *)data);
 | |
|    #endif
 | |
|    logDbfDate = data+16+ *(short *)data;
 | |
| 
 | |
|    c4->errOpen = 0;
 | |
|    if (destName != 0)
 | |
|    {
 | |
|       tempDbf = d4open(c4, destName);
 | |
|       outMess[1] = destName;
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       tempDbf = d4open(c4, addName);
 | |
|       outMess[1] = addName;
 | |
|    }
 | |
|    c4->errOpen = 1;
 | |
|    if (!tempDbf)
 | |
|    {
 | |
|       if (c4->errorCode != r4noOpen)
 | |
|          return(-1);
 | |
|       outMess[0] = "\r\n\r\nAccess error! Destination database:\r\n";
 | |
|       outMess[2] = "\r\ncan not be found.\r\n\r\n";
 | |
|       util4out(c4, stdout, outMess, 3);
 | |
|       return(-1);
 | |
|    }
 | |
| 
 | |
|    if ((unsigned)logRecordWidth != d4recWidth(tempDbf) || logNumFields != d4numFields(tempDbf) || logNumRecords != d4recCount(tempDbf))
 | |
|    {
 | |
|       d4close(tempDbf);
 | |
|       outMess[0] = "\r\n\r\nDBF Consistency error! Destination database:\r\n";
 | |
|       outMess[2] = "\r\nstructure or record count does not match log file entry.\r\n\r\n";
 | |
|       util4out(c4, stdout, outMess, 3);
 | |
|       return(-1);
 | |
|    }
 | |
| /*   if (tempDbf->dataFile->userCount == 1 && ((_fstat(tempDbf->dataFile->file.hand, &statbuf) == 0 && logDbfTime != statbuf.st_mtime) || strncmp(logDbfDate, &tempDbf->dataFile->yy, 3) != 0))
 | |
|    {
 | |
|       outMess[0] = "\r\n\r\nDBF Consistency warning! Destination database:\r\n";
 | |
|       outMess[2] = "\r\nfile time or internal date does not match log file entry, continuing.\r\n\r\n";
 | |
|       outMess[3] = statusStringBlank;
 | |
|       util4out(c4, stdout, outMess, 4);
 | |
|    }
 | |
| */
 | |
|    rc = d4appendStart(openDbfs, 0);
 | |
|    if (rc != 0)
 | |
|    {
 | |
|       d4close(tempDbf);
 | |
|       return(rc);
 | |
|    }
 | |
|    d4blank(openDbfs);
 | |
|    f4assignLong(d4field(openDbfs, "CLIENTID"), tran4clientId(t4));
 | |
|    f4assignLong(d4field(openDbfs, "SERVERDTID"), tran4serverDataId(t4));
 | |
|    f4assignLong(d4field(openDbfs, "DATA4PTR"), (long)tempDbf);
 | |
|    rc = d4append(openDbfs);
 | |
|    if (rc == r4unique)
 | |
|    {
 | |
|       outMess[0] = "\r\n\r\nLog file error! DBF identifier for:\r\n";
 | |
|       outMess[2] = "\r\nalready used.\r\n\r\n";
 | |
|       util4out(c4, stdout, outMess, 3);
 | |
|       d4close(tempDbf);
 | |
|    }
 | |
|    return(rc);
 | |
| }
 | |
| 
 | |
| /****************************************************************************
 | |
| **::  Function: typeTran4Close
 | |
| **
 | |
| *****************************************************************************
 | |
| **
 | |
| **    Function: typeTran4Close()
 | |
| **
 | |
| ****************************************************************************/
 | |
| static short typeTran4Close(CODE4 *c4, DATA4 *openDbfs, TRAN4 *t4)
 | |
| {
 | |
|    short rc;
 | |
|    char client[23];
 | |
| 
 | |
|    util4rightJ(ltoa(tran4clientId(t4), client, 10), 12);
 | |
|    util4rightJ(ltoa(tran4serverDataId(t4), client+11, 10), 12);
 | |
|    rc = d4seek(openDbfs, client);
 | |
|    if (rc != 0)
 | |
|    {
 | |
|       if (rc == r4after || rc == r4eof)
 | |
|          rc = 0;
 | |
|       return(rc);
 | |
|    }
 | |
|    d4delete(openDbfs);
 | |
|    return(rc);
 | |
| }
 | |
| 
 | |
| /****************************************************************************
 | |
| **::  Function: typeTran4Write
 | |
| **
 | |
| *****************************************************************************
 | |
| **
 | |
| **    Function: typeTran4Write()
 | |
| **
 | |
| ****************************************************************************/
 | |
| static short typeTran4Write(CODE4 *c4, DATA4 *openDbfs, DATA4 *tranDbf, TRAN4 *t4)
 | |
| {
 | |
|    DATA4 *tempDbf;
 | |
|    FIELD4 *tempField;
 | |
|    short rc, i, consistency=1;
 | |
|    unsigned short offset;
 | |
|    unsigned long offsetMemo;
 | |
|    char client[23], *outMess[5];
 | |
|    char *data;
 | |
|    char ltoaTemp[12];
 | |
|    char ltoaTemp2[12];
 | |
|    unsigned smallerSize;
 | |
| 
 | |
|    util4rightJ(ltoa(tran4id(t4), client, 10), 12);
 | |
|    rc = d4seek(tranDbf, client);
 | |
|    if (rc != 0)
 | |
|    {
 | |
|       if (rc == r4after || rc == r4eof)
 | |
|          rc = 0;     /* not rolledback */
 | |
|       else
 | |
|          return(rc);
 | |
|    }
 | |
|    else
 | |
|       return(0);     /* rolledback */
 | |
| 
 | |
|    util4rightJ(ltoa(tran4clientId(t4), client, 10), 12);
 | |
|    util4rightJ(ltoa(tran4serverDataId(t4), client+11, 10), 12);
 | |
|    rc = d4seek(openDbfs, client);
 | |
|    if (rc != 0)
 | |
|    {
 | |
|       if (rc == r4after || rc == r4eof)
 | |
|          rc = 0;
 | |
|       return(rc);
 | |
|    }
 | |
| 
 | |
|    tempDbf = (DATA4 *)f4long(d4field(openDbfs, "DATA4PTR"));
 | |
|    data = (char *)tran4getData(t4, 0L);
 | |
|    if (data == 0)
 | |
|       return(-1);
 | |
| 
 | |
|    c4->errGo = 0;
 | |
|    rc = d4go(tempDbf, *(long *)data);
 | |
|    c4->errGo = 1;
 | |
|    if (rc != 0)
 | |
|    {
 | |
|       if (rc == r4entry)
 | |
|       {
 | |
|          outMess[0] = "\r\n\r\nDBF consistency error!\r\nIn transaction #";
 | |
|          outMess[1] = ltoa(tran4id(t4), ltoaTemp, 10);
 | |
|          outMess[2] = ", write to DBF record #";
 | |
|          outMess[3] = ltoa(*(long *)data, ltoaTemp2, 10);
 | |
|          outMess[4] = " that does not exist.\r\n\r\n";
 | |
|          util4out(c4, stdout, outMess, 5);
 | |
|          rc = -1;
 | |
|       }
 | |
|       return(rc);
 | |
|    }
 | |
|    offset = 5;
 | |
|    offsetMemo = 4 + 2*d4recWidth(tempDbf);
 | |
|    if (*(data+offset-1) == '*')
 | |
|    {
 | |
|       if (!d4deleted(tempDbf))
 | |
|          consistency = 0;
 | |
|    }
 | |
|    else
 | |
|       if (d4deleted(tempDbf))
 | |
|          consistency = 0;
 | |
|    for (i=1; i<=d4numFields(tempDbf) && consistency == 1; i++)
 | |
|    {
 | |
|       tempField = d4fieldJ(tempDbf, i);
 | |
|       if (f4type(tempField) == 'M')
 | |
|       {
 | |
|          smallerSize = f4memoLen(tempField) < *(unsigned *)(data+offsetMemo) ? f4memoLen(tempField) : *(unsigned *)(data+offsetMemo);
 | |
|          if (strncmp(f4memoPtr(tempField), data+offsetMemo+4, smallerSize) != 0)
 | |
|             consistency = 0;
 | |
|          offsetMemo += 4 + *(unsigned long *)(data+offsetMemo);
 | |
|          offsetMemo += 4 + *(unsigned long *)(data+offsetMemo);
 | |
|          offset += 10;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|          if (strncmp(f4ptr(tempField), data+offset, f4len(tempField)) != 0)
 | |
|             consistency = 0;
 | |
|          offset += f4len(tempField);
 | |
|       }
 | |
|    }
 | |
|    if (consistency == 0)
 | |
|    {
 | |
|       outMess[0] = "\r\n\r\nDBF consistency error!\r\nIn transaction #";
 | |
|       outMess[1] = ltoa(tran4id(t4), ltoaTemp, 10);
 | |
|       outMess[2] = ", DBF record #";
 | |
|       outMess[3] = ltoa(*(long *)data, ltoaTemp2, 10);
 | |
|       outMess[4] = " does not match log file entry.\r\n\r\n";
 | |
|       util4out(c4, stdout, outMess, 5);
 | |
|       return(-1);
 | |
|    }
 | |
| 
 | |
|    offset = 5 + d4recWidth(tempDbf);
 | |
|    offsetMemo = 4 + 2*d4recWidth(tempDbf);
 | |
|    if (*(data+offset-1) == '*')
 | |
|       d4delete(tempDbf);
 | |
|    else
 | |
|       d4recall(tempDbf);
 | |
|    for (i=1; i<=d4numFields(tempDbf); i++)
 | |
|    {
 | |
|       tempField = d4fieldJ(tempDbf, i);
 | |
|       if (f4type(tempField) == 'M')
 | |
|       {
 | |
|          offsetMemo += 4 + *(unsigned long *)(data+offsetMemo);
 | |
|          if (*(unsigned long *)(data+offsetMemo) != 0)
 | |
|             f4memoAssignN(tempField, data+offsetMemo+4, *(unsigned *)(data+offsetMemo));
 | |
|          offsetMemo += 4 + *(unsigned long *)(data+offsetMemo);
 | |
|          offset += 10;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|          f4assignN(tempField, data+offset, f4len(tempField));
 | |
|          offset += f4len(tempField);
 | |
|       }
 | |
|    }
 | |
|    return(rc);
 | |
| }
 | |
| 
 | |
| /****************************************************************************
 | |
| **::  Function: typeTran4Append
 | |
| **
 | |
| *****************************************************************************
 | |
| **
 | |
| **    Function: typeTran4Append()
 | |
| **
 | |
| ****************************************************************************/
 | |
| static short typeTran4Append(CODE4 *c4, DATA4 *openDbfs, DATA4 *tranDbf, TRAN4 *t4)
 | |
| {
 | |
|    DATA4 *tempDbf;
 | |
|    FIELD4 *tempField;
 | |
|    short rc, i;
 | |
|    unsigned short offset;
 | |
|    unsigned long offsetMemo;
 | |
|    char client[23], *outMess[5];
 | |
|    char *data;
 | |
|    char ltoaTemp[12];
 | |
|    char ltoaTemp2[12];
 | |
| 
 | |
|    util4rightJ(ltoa(tran4id(t4), client, 10), 12);
 | |
|    rc = d4seek(tranDbf, client);
 | |
|    if (rc != 0)
 | |
|    {
 | |
|       if (rc == r4after || rc == r4eof)
 | |
|          rc = 0;     /* not rolledback */
 | |
|       else
 | |
|          return(rc);
 | |
|    }
 | |
|    else
 | |
|       return(0);     /* rolledback */
 | |
| 
 | |
|    util4rightJ(ltoa(tran4clientId(t4), client, 10), 12);
 | |
|    util4rightJ(ltoa(tran4serverDataId(t4), client+11, 10), 12);
 | |
|    rc = d4seek(openDbfs, client);
 | |
|    if (rc != 0)
 | |
|    {
 | |
|       if (rc == r4after || rc == r4eof)
 | |
|          rc = 0;
 | |
|       return(rc);
 | |
|    }
 | |
| 
 | |
|    tempDbf = (DATA4 *)f4long(d4field(openDbfs, "DATA4PTR"));
 | |
|    data = (char *)tran4getData(t4, 0L);
 | |
|    if (data == 0)
 | |
|       return(-1);
 | |
| 
 | |
|    if (*(long *)data != d4recCount(tempDbf)+1)
 | |
|    {
 | |
|       outMess[0] = "\r\n\r\nDBF consistency error!\r\nIn transaction #";
 | |
|       outMess[1] = ltoa(tran4id(t4), ltoaTemp, 10);
 | |
|       outMess[2] = ", DBF record #";
 | |
|       outMess[3] = ltoa(*(long *)data, ltoaTemp2, 10);
 | |
|       outMess[4] = " would not be the appended record number.\r\n\r\n";
 | |
|       util4out(c4, stdout, outMess, 5);
 | |
|       return(-1);
 | |
|    }
 | |
| 
 | |
|    rc = d4appendStart(tempDbf,0);
 | |
|    if (rc != 0)
 | |
|       return(rc);
 | |
|    offset = 5;
 | |
|    offsetMemo = 4 + d4recWidth(tempDbf);
 | |
|    if (*(data+offset-1) == '*')
 | |
|       d4delete(tempDbf);
 | |
|    for (i=1; i<=d4numFields(tempDbf); i++)
 | |
|    {
 | |
|       tempField = d4fieldJ(tempDbf, i);
 | |
|       if (f4type(tempField) == 'M')
 | |
|       {
 | |
|          if (*(unsigned long *)(data+offsetMemo) != 0)
 | |
|             f4memoAssignN(tempField, data+offsetMemo+4, *(unsigned *)(data+offsetMemo));
 | |
|          offsetMemo += 4 + *(unsigned long *)(data+offsetMemo);
 | |
|          offset += 10;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|          f4assignN(tempField, data+offset, f4len(tempField));
 | |
|          offset += f4len(tempField);
 | |
|       }
 | |
|    }
 | |
|    rc = d4append(tempDbf);
 | |
|    return(rc);
 | |
| }
 | |
| 
 | |
| /****************************************************************************
 | |
| **::  Function: typeTran4PackZap
 | |
| **
 | |
| *****************************************************************************
 | |
| **
 | |
| **    Function: typeTran4PackZap()
 | |
| **
 | |
| ****************************************************************************/
 | |
| static short typeTran4PackZap(CODE4 *c4, DATA4 *openDbfs, TRAN4 *t4)
 | |
| {
 | |
|    DATA4 *tempDbf;
 | |
|    short rc;
 | |
|    char client[23], *outMess[1];
 | |
|    char *data;
 | |
| 
 | |
|    util4rightJ(ltoa(tran4clientId(t4), client, 10), 12);
 | |
|    util4rightJ(ltoa(tran4serverDataId(t4), client+11, 10), 12);
 | |
|    rc = d4seek(openDbfs, client);
 | |
|    if (rc != 0)
 | |
|    {
 | |
|       if (rc == r4after || rc == r4eof)
 | |
|          rc = 0;
 | |
|       return(rc);
 | |
|    }
 | |
| 
 | |
|    tempDbf = (DATA4 *)f4long(d4field(openDbfs, "DATA4PTR"));
 | |
|    if (tran4type(t4) == TRAN4ZAP)
 | |
|    {
 | |
|       data = (char *)tran4getData(t4, 0L);
 | |
|       if (!data)
 | |
|          return(-1);
 | |
|       if (*(long *)data < 1 || *(long *)(data+4) > d4recCount(tempDbf))
 | |
|       {
 | |
|          outMess[0] = "\r\n\r\nDBF consistency error! Record number range for zap is invalid.\r\n\r\n";
 | |
|          util4out(c4, stdout, outMess, 1);
 | |
|          return(-1);
 | |
|       }
 | |
|       rc = d4zap(tempDbf, *(long *)data, *(long *)(data+4));
 | |
|    }
 | |
|    else
 | |
|       rc = d4pack(tempDbf);
 | |
|    return(rc);
 | |
| }
 | |
| 
 | |
| /****************************************************************************
 | |
| **::  Function: doLogFile
 | |
| **
 | |
| *****************************************************************************
 | |
| **
 | |
| **    Function: doLogFile()
 | |
| **
 | |
| ****************************************************************************/
 | |
| static int doLogFile(CODE4 *c4, UTIL4FLAG u4flags[], int u4flagsNum, int all, int exclusive, int index)
 | |
| {
 | |
|    DATA4 *openDbfs, *tranDbf, *tempDbf;
 | |
|    TRAN4 *t4;
 | |
|    FIELD4 *data4Ptr;
 | |
|    short rc, rc2, intPart, decPart;
 | |
|    char *outMess[3], client[23];
 | |
|    long logFileLen;
 | |
|    TRAN4ENTRY_LEN len;
 | |
| 
 | |
|    rc = file4refresh(&c4->transFile.file);
 | |
|    if (rc != 0)
 | |
|       return(rc);
 | |
|    logFileLen = file4len(&c4->transFile.file);
 | |
|    if (logFileLen < 0)
 | |
|       return((short)logFileLen);
 | |
| 
 | |
|    t4 = &c4->c4trans.trans;
 | |
|    openDbfs = d4createTemp(c4, openFields, openTags);
 | |
|    if (openDbfs == 0)
 | |
|       return(-1);
 | |
|    tranDbf = d4createTemp(c4, tranFields, tranTags);
 | |
|    if (tranDbf == 0)
 | |
|    {
 | |
|       d4close(openDbfs);
 | |
|       return(-1);
 | |
|    }
 | |
| #ifdef N4OTHER
 | |
|    c4->autoOpen = 0;
 | |
| #else
 | |
|    if (index == 0 || exclusive == 1)
 | |
|       c4->autoOpen = 0;
 | |
| #endif
 | |
|    d4tagSelect(openDbfs, d4tag(openDbfs, "CLID"));
 | |
|    d4tagSelect(tranDbf, d4tag(tranDbf, "TRANID"));
 | |
|    #ifndef S4WINDOWS
 | |
|       outMess[0] = statusStringBlank;
 | |
|       util4out(c4, stderr, outMess, 1);
 | |
|    #endif
 | |
| 
 | |
|    for (rc = tran4top(t4); rc == 0; rc = tran4skip(t4, TRAN4FORWARDS))
 | |
|    {
 | |
|       intPart = (short)((unsigned long)c4->c4trans.trans.pos*50/logFileLen);
 | |
|       decPart = (short)((unsigned long)c4->c4trans.trans.pos*5000/logFileLen%100);
 | |
|       #ifndef S4WINDOWS
 | |
|          sprintf(statusStringSpace, statusStringFormt, intPart, decPart);
 | |
|          outMess[0] = statusStringBckSp;
 | |
|          outMess[1] = statusStringMessg;
 | |
|          outMess[2] = statusStringSpace;
 | |
|          util4out(c4, stderr, outMess, 3);
 | |
|       #else
 | |
|          sendStatusMessage( hWndStatus, intPart ) ;
 | |
|       #endif
 | |
| 
 | |
|       switch (tran4type(t4))
 | |
|       {
 | |
|          case TRAN4SHUTDOWN:
 | |
|          case TRAN4BACKEDUP:
 | |
|          case TRAN4INIT:
 | |
|          case TRAN4INIT_UNDO:
 | |
|          case TRAN4OPEN:
 | |
|          case TRAN4OPEN_TEMP:
 | |
|          case TRAN4CLOSE:
 | |
|          case TRAN4WRITE:
 | |
|          case TRAN4APPEND:
 | |
|          case TRAN4PACK:
 | |
|          case TRAN4ZAP:
 | |
|          case TRAN4VOID:
 | |
|          case TRAN4ROLLBACK:
 | |
|             break;
 | |
| 
 | |
|          case TRAN4START:
 | |
|             rc = d4appendStart(tranDbf, 0);
 | |
|             if (rc != 0)
 | |
|                break;
 | |
|             d4blank(tranDbf);
 | |
|             f4assignLong(d4field(tranDbf, "TRANID"), tran4id(t4));
 | |
|             rc = d4append(tranDbf);
 | |
|             if (rc == r4unique)
 | |
|             {
 | |
|                outMess[0] = "\r\n\r\nLog file error! Transaction ID already started.\r\n\r\n";
 | |
|                util4out(c4, stdout, outMess, 1);
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|          case TRAN4COMPLETE:
 | |
|             util4rightJ(ltoa(tran4id(t4), client, 10), 12);
 | |
|             rc = d4seek(tranDbf, client);
 | |
|             if (rc != 0)
 | |
|             {
 | |
|                if (rc == r4after || rc == r4eof)
 | |
|                {
 | |
|                   outMess[0] = "\r\n\r\nLog file error! Transaction completed that was not started.\r\n\r\n";
 | |
|                   util4out(c4, stdout, outMess, 1);
 | |
|                   rc = -1;
 | |
|                }
 | |
|                break;
 | |
|             }
 | |
|             d4delete(tranDbf);
 | |
|             break;
 | |
| 
 | |
|          default:
 | |
|             outMess[0] = "\r\n\r\nLog file error! Unknown log entry type.\r\n\r\n";
 | |
|             util4out(c4, stdout, outMess, 1);
 | |
|             rc = -1;
 | |
|       }
 | |
|       if (rc != 0)
 | |
|          break;
 | |
|       if (t4->pos+sizeof(LOG4HEADER)+sizeof(TRAN4ENTRY_LEN) > logFileLen)
 | |
|       {
 | |
|          rc = r4eof;
 | |
|          break;
 | |
|       }
 | |
|       rc = file4readAll(&c4->transFile.file, t4->pos+sizeof(LOG4HEADER), &len, sizeof(TRAN4ENTRY_LEN));
 | |
|       if (rc == 0 && (long)(t4->pos+sizeof(LOG4HEADER)+len) > logFileLen)
 | |
|       {
 | |
|          rc = r4eof;
 | |
|          break;
 | |
|       }
 | |
|       if (rc != 0)
 | |
|          break;
 | |
|    }
 | |
| 
 | |
|    if (rc == r4eof)
 | |
|    {
 | |
|       for (rc = tran4top(t4); rc == 0; rc = tran4skip(t4, TRAN4FORWARDS))
 | |
|       {
 | |
|          intPart = (short)((unsigned long)c4->c4trans.trans.pos*50/logFileLen+50);
 | |
|          decPart = (short)((unsigned long)c4->c4trans.trans.pos*5000/logFileLen%100);
 | |
|          #ifndef S4WINDOWS
 | |
|             sprintf(statusStringSpace, statusStringFormt, intPart, decPart);
 | |
|             outMess[0] = statusStringBckSp;
 | |
|             outMess[1] = statusStringMessg;
 | |
|             outMess[2] = statusStringSpace;
 | |
|             util4out(c4, stderr, outMess, 3);
 | |
|          #else
 | |
|             sendStatusMessage( hWndStatus, intPart ) ;
 | |
|          #endif
 | |
| 
 | |
|          switch (tran4type(t4))
 | |
|          {
 | |
|             case TRAN4SHUTDOWN:
 | |
|             case TRAN4BACKEDUP:
 | |
|             case TRAN4INIT:
 | |
|             case TRAN4INIT_UNDO:
 | |
|             case TRAN4OPEN_TEMP:
 | |
|             case TRAN4START:
 | |
|             case TRAN4COMPLETE:
 | |
|             case TRAN4ROLLBACK:
 | |
|             case TRAN4VOID:
 | |
|                break;
 | |
| 
 | |
|             case TRAN4OPEN:
 | |
|                rc = typeTran4Open(c4, u4flags, u4flagsNum, openDbfs, t4, all);
 | |
|                break;
 | |
| 
 | |
|             case TRAN4CLOSE:
 | |
|                rc = typeTran4Close(c4, openDbfs, t4);
 | |
|                break;
 | |
| 
 | |
|             case TRAN4WRITE:
 | |
|                rc = typeTran4Write(c4, openDbfs, tranDbf, t4);
 | |
|                break;
 | |
| 
 | |
|             case TRAN4APPEND:
 | |
|                rc = typeTran4Append(c4, openDbfs, tranDbf, t4);
 | |
|                break;
 | |
| 
 | |
|             case TRAN4PACK:
 | |
|             case TRAN4ZAP:
 | |
|                rc = typeTran4PackZap(c4, openDbfs, t4);
 | |
|                break;
 | |
| 
 | |
|             default:
 | |
|                outMess[0] = "\r\n\r\nLog file error! Unknown log entry type.\r\n\r\n";
 | |
|                util4out(c4, stdout, outMess, 1);
 | |
|                rc = -1;
 | |
|          }
 | |
|          if (rc != 0)
 | |
|          {
 | |
|             if (rc == r4bof || rc == r4eof)
 | |
|                rc = -1;
 | |
|             break;
 | |
|          }
 | |
|          if (t4->pos+sizeof(LOG4HEADER)+sizeof(TRAN4ENTRY_LEN) > logFileLen)
 | |
|          {
 | |
|             rc = r4eof;
 | |
|             break;
 | |
|          }
 | |
|          rc = file4readAll(&c4->transFile.file, t4->pos+sizeof(LOG4HEADER), &len, sizeof(TRAN4ENTRY_LEN));
 | |
|          if (rc == 0 && (long)(t4->pos+sizeof(LOG4HEADER)+len) > logFileLen)
 | |
|          {
 | |
|             rc = r4eof;
 | |
|             break;
 | |
|          }
 | |
|          if (rc != 0)
 | |
|             break;
 | |
|       }
 | |
|       if (rc == r4eof)
 | |
|          rc = 0;
 | |
|    }
 | |
| 
 | |
|    if (rc == 0)
 | |
|    {
 | |
|       #ifndef S4WINDOWS
 | |
|          outMess[0] = statusStringBckSp;
 | |
|          outMess[1] = statusStringMessg;
 | |
|          sprintf(statusStringSpace, statusStringFormt, 100, 0);
 | |
|          outMess[2] = statusStringSpace;
 | |
|          util4out(c4, stderr, outMess, 3);
 | |
|       #endif
 | |
|    }
 | |
| 
 | |
|    #ifndef S4WINDOWS
 | |
|       outMess[0] = "\r\n";
 | |
|       util4out(c4, stderr, outMess, 1);
 | |
|       util4out(c4, stdout, outMess, 1);
 | |
|    #endif
 | |
|    rc2 = rc;
 | |
|    d4tagSelect(openDbfs, 0);
 | |
|    data4Ptr = d4field(openDbfs, "DATA4PTR");
 | |
|    for (rc = d4top(openDbfs); rc == 0; rc = d4skip(openDbfs, 1L))
 | |
|    {
 | |
|       tempDbf = (DATA4 *)f4long(data4Ptr);
 | |
|       if (!d4deleted(openDbfs))
 | |
|       {
 | |
|          outMess[0] = "Log file warning! DBF file opened but not closed, continuing.\r\n\r\n";
 | |
|          util4out(c4, stdout, outMess, 1);
 | |
|       }
 | |
| #ifndef N4OTHER
 | |
|       if (rc2 == 0 && index == 1 && exclusive == 1 && tempDbf->dataFile->userCount == 1)
 | |
|       {
 | |
|          if (tempDbf->dataFile->hasMdxMemo)
 | |
|          {
 | |
|             if (i4open(tempDbf, 0) == 0)
 | |
|                rc2 = -1;
 | |
|             if (rc2 == 0)
 | |
|                rc2 = d4reindex(tempDbf);
 | |
|          }
 | |
|       }
 | |
| #endif
 | |
|       rc2 = rc2 || d4close(tempDbf);
 | |
|    }
 | |
|    if (rc == r4eof)
 | |
|       rc = rc2;
 | |
|    rc = rc || d4close(tranDbf);
 | |
|    rc = rc || d4close(openDbfs);
 | |
|    return(rc);
 | |
| }
 | |
| 
 | |
| /****************************************************************************
 | |
| **::  Function: main
 | |
| **
 | |
| *****************************************************************************
 | |
| **
 | |
| **    Function: main()
 | |
| **
 | |
| ****************************************************************************/
 | |
| #ifdef S4DLL_BUILD
 | |
| int S4FUNCTION  mainLog4Res(int argc, char *argv[], int hWnd )
 | |
| #else
 | |
| int main(int argc, char *argv[])
 | |
| #endif
 | |
| {
 | |
|    CODE4 c4;
 | |
|    int rc=0, all, exclusive, index;
 | |
|    char *outMess[3];
 | |
| 
 | |
|    #ifdef S4WINDOWS
 | |
|       hWndStatus = hWnd ;
 | |
|       messageType = MB_ICONSTOP ;
 | |
|    #endif
 | |
| 
 | |
|    #ifndef S4DLL_BUILD
 | |
|    #ifdef _WINDOWS
 | |
|       _wabout("LOG4RES.EXE\r\n(c)Copyright Sequiter Software Inc., 1988-1996");
 | |
|    #endif
 | |
|    #endif
 | |
| 
 | |
|    code4init(&c4);
 | |
|    c4.lockAttempts = WAIT4EVER;
 | |
|    c4.singleOpen = 0 ;
 | |
| 
 | |
|    /* evaluate command line parameters */
 | |
|    #ifndef S4WINDOWS
 | |
|       outMess[0] = "\r\n";
 | |
|       util4out(&c4, stderr, outMess, 1);
 | |
|    #endif
 | |
|    if (argc < 2)
 | |
|       rc = -1;
 | |
|    if (rc == 0)
 | |
|       rc = util4parseCommandLine(&c4, u4flags, u4flagsNum, argv, argc);
 | |
|    if (rc == 0 && u4flags[UTIL4LOG].found == 0)
 | |
|    {
 | |
|       outMess[0] = "Command line error! Must specify -log switch.\r\n\r\n";
 | |
|       util4out(&c4, stdout, outMess, 1);
 | |
|       rc = -1;
 | |
|    }
 | |
|    all = util4checkOnOffCommandLine(&c4, u4flags, UTIL4ALL, 0);
 | |
|    if (all == -1)
 | |
|       rc = -1;
 | |
|    exclusive = util4checkOnOffCommandLine(&c4, u4flags, UTIL4EXCLUSIVE, 1);
 | |
|    if (exclusive == -1)
 | |
|       rc = -1;
 | |
|    else
 | |
|       c4.accessMode = exclusive * OPEN4DENY_RW;
 | |
|    index = util4checkOnOffCommandLine(&c4, u4flags, UTIL4INDEX, 0);
 | |
|    if (index == -1)
 | |
|       rc = -1;
 | |
|    if (rc != 0)
 | |
|    {
 | |
|       util4printCommandLine(&c4, u4flags, u4flagsNum, argv[0]);
 | |
|       util4flagsFree(u4flags, u4flagsNum);
 | |
|       code4initUndo(&c4);
 | |
|       #ifdef S4WINDOWS
 | |
|          sendCloseMessage( hWndStatus ) ;
 | |
|       #endif
 | |
|       return(rc);
 | |
|    }
 | |
| 
 | |
|    /* initialize log file */
 | |
|    if (rc == 0)
 | |
|    {
 | |
| 
 | |
|       rc = code4logOpen( &c4, u4flags[UTIL4LOG].ptr[0], "" ) ;
 | |
| /*    rc = code4tranInit2(&c4, u4flags[UTIL4LOG].ptr[0], 0);  */
 | |
|       code4tranStatusSet(&c4, r4off);
 | |
|    }
 | |
|    if (rc == 0 && sizeof(LOG4HEADER)+sizeof(TRAN4ENTRY_LEN) > file4len(&c4.transFile.file))
 | |
|    {
 | |
|       rc = file4lenSet(&c4.transFile.file, 0L);
 | |
|       outMess[0] = "Log file error! Log file is empty.\r\n\r\n";
 | |
|       util4out(&c4, stdout, outMess, 1);
 | |
|       rc = -1;
 | |
|    }
 | |
|    c4.lockAttempts = 1;
 | |
|    if (rc == 0)
 | |
|    {
 | |
|       rc = code4tranLockTransactions(&c4.c4trans, TRAN4LOCK_RESTORE);
 | |
|       if (rc == r4locked)
 | |
|       {
 | |
|          outMess[0] = "Concurrency error! Another copy of this utility is running!\r\n\r\n";
 | |
|          util4out(&c4, stdout, outMess, 1);
 | |
|       }
 | |
|    }
 | |
|    if (rc == 0)
 | |
|    {
 | |
|       rc = code4tranLockTransactions(&c4.c4trans, TRAN4LOCK_BACKUP);
 | |
|       if (rc == r4locked)
 | |
|       {
 | |
|          outMess[0] = "Concurrency error! Backup utility is using -log file ";
 | |
|          outMess[1] = u4flags[UTIL4LOG].ptr[0];
 | |
|          outMess[2] = "!\r\n\r\n";
 | |
|          util4out(&c4, stdout, outMess, 3);
 | |
|       }
 | |
|    }
 | |
|    c4.lockAttempts = WAIT4EVER;
 | |
|    if (rc == 0)
 | |
|    {
 | |
|       rc = tran4top(&c4.c4trans.trans);
 | |
|       if (rc == 0 && (tran4type(&c4.c4trans.trans) != TRAN4BACKEDUP || tran4serverDataId(&c4.c4trans.trans) > TRAN4VERSION_NUM))
 | |
|       {
 | |
|          outMess[0] = "Log file error! File is either not a backup file or a newer version than this utility can handle!\r\n\r\n";
 | |
|          util4out(&c4, stdout, outMess, 1);
 | |
|          rc = -1;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if (rc == 0)
 | |
|       rc = doLogFile(&c4, u4flags, u4flagsNum, all, exclusive, index);
 | |
| 
 | |
|    if (rc == 0)
 | |
|    {
 | |
|       #ifdef S4WINDOWS
 | |
|          messageType = MB_ICONEXCLAMATION ;
 | |
|          sendStatusMessage( hWndStatus, 100 ) ;
 | |
|       #endif
 | |
|       outMess[0] = "Utility successfully finished!\r\n\r\n";
 | |
|    }
 | |
|    else
 | |
|       outMess[0] = "Error! Utility did not successfully finish!\r\n\r\n";
 | |
|    util4out(&c4, stdout, outMess, 1);
 | |
|    code4transInitUndo(&c4.c4trans);
 | |
|    util4flagsFree(u4flags, u4flagsNum);
 | |
|    code4initUndo(&c4);
 | |
|    #ifdef S4WINDOWS
 | |
|       sendCloseMessage( hWndStatus ) ;
 | |
|    #endif
 | |
|    return(rc);
 | |
| }
 | |
| 
 |