Files
microser/mmslib/slog/slogfil.c

742 lines
20 KiB
C
Raw Normal View History

2026-06-15 15:48:16 +08:00
/************************************************************************/
/* SISCO SOFTWARE MODULE HEADER *****************************************/
/************************************************************************/
/* (c) Copyright Systems Integration Specialists Company, Inc., */
/* 1993-2008, All Rights Reserved */
/* */
/* MODULE NAME : slogfil.c */
/* PRODUCT(S) : SLOG */
/* */
/* MODULE DESCRIPTION : */
/* */
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
/* */
/* MODIFICATION LOG : */
/* Date Who Rev Comments */
/* -------- --- ------ ------------------------------------------- */
/* 03/27/08 EJV 22 Elim warning from previous changes. */
/* 03/27/08 EJV 21 Use S_MAX_PATH instead of MAX_PATH. */
/* slog_get_index_file_name: added destLen param*/
/* and changed to return result. */
/* 10/08/07 EJV 20 Moved MAX_PATH define to sysincs.h */
/* 01/15/07 EJV 19 Chg S_LOCK_RESOURCES to S_LOCK_UTIL_RESOURCES*/
/* 02/13/06 DSF 18 Migrate to VS.NET 2005 */
/* 10/31/05 MDE 17 Tweaked index tile name creation */
/* 09/23/05 MDE 16 Tweaked size of idxFileName in */
/* 09/14/05 DSF 15 Increased size of idxFileName in */
/* 08/26/05 MDE 14 Fixed startup w/wo */
/* 08/10/05 MDE 13 Added index file, wrap cleanup, etc. */
/* 06/07/04 EJV 12 slogFil: chg state if reopen err (HARD_FLUSH)*/
/* 05/13/04 EJV 11 Moved log header formatting to slogSetHdr. */
/* 03/11/04 GLB 10 Remove "thisFileName" */
/* 02/20/03 JRB 09 Del PSOS code. */
/* 10/13/00 EJV 08 Moved glbsem.h below sysincs.h. */
/* 08/22/00 KCR 07 Added FIL_CTRL_NO_LOG_HDR */
/* 09/13/99 MDE 06 Added SD_CONST modifiers */
/* 04/14/99 MDE 05 Removed unnecessary include files */
/* 10/23/98 MDE 04 No blank line bet. logs if LOG_NO_HEADER_CR */
/* 10/16/98 DSF 03 Spelling */
/* 10/08/98 MDE 02 Migrated to updated SLOG interface */
/* 10/06/97 DSF 01 Added thisFileName */
/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */
/* history. */
/************************************************************************/
#if defined (_WIN32)
#pragma warning(disable : 4996)
#endif
#include "glbtypes.h"
#include "sysincs.h"
#include "glbsem.h"
#include <errno.h>
#if defined(_WIN32)
#include "io.h"
#endif
#include "slog.h"
/************************************************************************/
/* Do not change w/o testing */
#define OLDEST_STRING " OLDEST DATA STARTS BELOW"
/************************************************************************/
/* Local function prototypes */
/************************************************************************/
static ST_VOID printWipe (FILE *fh);
static ST_VOID printWrap (FILE *fh);
static ST_VOID printStart (FILE *fh);
static ST_VOID slogFileErrorPrint(ST_CHAR *text, ST_CHAR *fname);
static ST_LONG findOldestMessage(LOG_CTRL *lc, FILE *fh);
static ST_INT copy_named_files (LOG_CTRL *lc, SD_CONST ST_CHAR *SD_CONST dest,
SD_CONST ST_CHAR *SD_CONST src);
static ST_INT copy_named_files_ex (LOG_CTRL *lc, SD_CONST ST_CHAR *SD_CONST dest,
SD_CONST ST_CHAR *SD_CONST src);
static ST_VOID chk_slog_service (LOG_CTRL *lc);
/************************************************************************/
/* slogFile */
/************************************************************************/
ST_VOID slogFile (LOG_CTRL *lc, SD_CONST ST_INT logType,
SD_CONST ST_CHAR *SD_CONST logTypeStr,
SD_CONST ST_CHAR *SD_CONST sourceFile,
SD_CONST ST_INT lineNum,
SD_CONST ST_INT bufLen, SD_CONST ST_CHAR *buf)
{
FILE *fh;
struct stat fileStat;
ST_LONG seekPos;
ST_LONG currPos;
ST_ULONG fileSize;
ST_CHAR slogHdr[SLOG_MAX_HDR + 1];
/*ST_INT wrap; */
if (!(lc->fc.state & FIL_STATE_OPEN)) /* if not already opened */
{
/* Need to open the file */
if (lc->fc.ctrl & FIL_CTRL_NO_APPEND) /* If overwrite is requested */
fh = NULL;
else
lc->fc.fp = fh = fopen (lc->fc.fileName,"r+");
if (!fh) /* File must not exist, or overwrite requested */
{ /* try creating it */
lc->fc.fp = fh = fopen (lc->fc.fileName,"w+");
if (!fh)
{
slogFileErrorPrint ("OPEN",lc->fc.fileName);
return;
}
}
/* We have successfully opened the log file */
lc->fc.state = FIL_STATE_OPEN;
if (lc->fc.ctrl & FIL_CTRL_SETBUF_EN) /* If setbuf desired */
setbuf (fh,NULL); /* no buffering, please */
/* If appending, need to get to the start write position */
if ((lc->fc.ctrl & FIL_CTRL_NO_APPEND) == 0)
{
/* Check the current file size, see if we can just append */
if (fstat (fileno(fh), &fileStat))
{
slogFileErrorPrint ("SEEK",lc->fc.fileName);
return;
}
fileSize = fileStat.st_size;
if (fileSize < lc->fc.maxSize)
seekPos = (ST_LONG) fileSize;
else
{
seekPos = findOldestMessage (lc, fh);
lc->fc.state |= FIL_STATE_NEED_WIPE; /* flag to show we wrapped */
}
if (fseek (fh,seekPos,SEEK_SET))
{
slogFileErrorPrint ("SEEK",lc->fc.fileName);
return;
}
}
/* Print the 'started' message */
if (!(lc->fc.ctrl & FIL_CTRL_NO_LOG_HDR)) /* log file header */
printStart (fh);
}/* File not opened */
else
{ /* The file has already been opened for logging */
fh = lc->fc.fp;
if (lc->fc.ctrl & FIL_CTRL_WRAP_EN) /* if wrap allowed */
{
/* Check to see the position of the file to see if we need to wrap it */
currPos = ftell (fh);
if (currPos == -1L)
{
slogFileErrorPrint ("TELL",lc->fc.fileName);
return;
}
/* Check to see if we need to wrap - currPos is where we would write */
if (((ST_ULONG) currPos > lc->fc.maxSize))
{
/* Yep, need to wrap - cut off the rest of the file to avoid trailing */
#if defined(MSDOS) || defined(__OS2__) || defined(_WIN32)
if (chsize (fileno(fh), currPos))
{
slogFileErrorPrint ("CHSIZE",lc->fc.fileName);
}
#else
#ifndef __ECOS
if (ftruncate (fileno(fh), currPos))
{
slogFileErrorPrint ("FTRUNCATE",lc->fc.fileName);
}
#endif
#endif
/* Seek to start of file */
if (fseek (fh,0L,SEEK_SET))
{
slogFileErrorPrint ("SEEK",lc->fc.fileName);
return;
}
/* Print wrap message at top */
seekPos = 0;
printWrap (fh);
lc->fc.state |= FIL_STATE_NEED_WIPE; /* flag to show we wrapped */
} /* need to wrap */
} /* Wrap not disabled */
} /* File already opened */
/* Ok, the file is open and the pointer set to where we log the next */
/* message, any wrap has been printed - time to log the info */
/* Now print the message header */
slogSetHdr (lc, logType, logTypeStr, sourceFile, lineNum, slogHdr, "\n");
fprintf (fh,"%s", slogHdr);
/* Now print the message buffer */
fprintf (fh,"%s", buf);
/* Now print 'wipe bar', if file has wrapped some time in the past */
/* and if we are supposed to do the wipe */
if (lc->fc.state & FIL_STATE_NEED_WIPE &&
lc->fc.ctrl & FIL_CTRL_WIPE_EN)
{
currPos = ftell (fh);
if (currPos == -1L)
{
slogFileErrorPrint ("TELL",lc->fc.fileName);
return;
}
/* Print the wipe bar */
lc->fc.wipeFilePos = currPos;
printWipe (fh);
/* Seek to the current write position */
if (fseek (fh,currPos,SEEK_SET))
{
slogFileErrorPrint ("SEEK",lc->fc.fileName);
return;
}
} /* Need to print wipe bar */
/* Try to not lose log data */
fflush (fh);
/* Check for paranoid user - wants to close && reopen */
if (lc->fc.ctrl & FIL_CTRL_HARD_FLUSH)
{
currPos = ftell (fh);
if (currPos == -1L)
{
slogFileErrorPrint ("TELL",lc->fc.fileName);
return;
}
/* Close the file */
fclose (fh);
/* Re-open the file */
lc->fc.fp = fh = fopen (lc->fc.fileName,"r+");
if (!fh) /* better exist */
{
slogFileErrorPrint ("OPEN",lc->fc.fileName);
lc->fc.state &= ~FIL_STATE_OPEN;
return;
}
if (lc->fc.ctrl & FIL_CTRL_SETBUF_EN) /* If setbuf desired */
setbuf (fh,NULL); /* no buffering, please */
/* Seek to current write position */
if (fseek (fh,currPos,SEEK_SET))
{
slogFileErrorPrint ("SEEK",lc->fc.fileName);
return;
}
} /* if hard flush enabled */
}
/************************************************************************/
/* slogCloseFile */
/************************************************************************/
ST_VOID slogCloseFile (LOG_CTRL *lc)
{
S_GS_INIT ();
S_LOCK_UTIL_RESOURCES ();
if (lc->fc.state & FIL_STATE_OPEN)
{
if (fclose (lc->fc.fp))
{
fprintf (stderr,"\n *** LOG FILE CLOSE PROBLEM (%s) : ",
lc->fc.fileName);
return;
}
lc->fc.state &= ~FIL_STATE_OPEN;
}
S_UNLOCK_UTIL_RESOURCES ();
}
/************************************************************************/
/* slogCloneFile */
/************************************************************************/
ST_VOID slogCloneFile (LOG_CTRL *lc, SD_CONST ST_CHAR *newFile)
{
ST_LONG currPos;
FILE *fh;
S_GS_INIT ();
S_LOCK_UTIL_RESOURCES ();
fh = lc->fc.fp;
if (lc->fc.state & FIL_STATE_OPEN)
{
currPos = ftell (fh);
if (currPos == -1L)
{
slogFileErrorPrint ("TELL",lc->fc.fileName);
S_UNLOCK_UTIL_RESOURCES ();
return;
}
/* Close the file */
fclose (fh);
/* Copy the log file */
copy_named_files (lc, newFile, lc->fc.fileName);
/* Re-open the file at the old position */
lc->fc.fp = fh = fopen (lc->fc.fileName,"r+");
if (!fh) /* better exist */
{
slogFileErrorPrint ("OPEN",lc->fc.fileName);
S_UNLOCK_UTIL_RESOURCES ();
return;
}
if (lc->fc.ctrl & FIL_CTRL_SETBUF_EN) /* If setbuf desired */
setbuf (fh,NULL); /* no buffering, please */
/* Seek to current write position */
if (fseek (fh,currPos,SEEK_SET))
{
slogFileErrorPrint ("SEEK",lc->fc.fileName);
S_UNLOCK_UTIL_RESOURCES ();
return;
}
}
else /* log file not opened, just copy it */
copy_named_files (lc, newFile, lc->fc.fileName);
S_UNLOCK_UTIL_RESOURCES ();
}
/************************************************************************/
/* slogCloneFileEx */
/************************************************************************/
ST_VOID slogCloneFileEx (LOG_CTRL *lc, SD_CONST ST_CHAR *newFile)
{
ST_LONG currPos;
FILE *fh;
S_GS_INIT ();
S_LOCK_UTIL_RESOURCES ();
fh = lc->fc.fp;
if (lc->fc.state & FIL_STATE_OPEN)
{
currPos = ftell (fh);
if (currPos == -1L)
{
slogFileErrorPrint ("TELL",lc->fc.fileName);
S_UNLOCK_UTIL_RESOURCES ();
return;
}
/* Close the file */
fclose (fh);
/* Copy the log file */
copy_named_files_ex (lc, newFile, lc->fc.fileName);
/* Re-open the file at the old position */
lc->fc.fp = fh = fopen (lc->fc.fileName,"r+");
if (!fh) /* better exist */
{
slogFileErrorPrint ("OPEN",lc->fc.fileName);
S_UNLOCK_UTIL_RESOURCES ();
return;
}
if (lc->fc.ctrl & FIL_CTRL_SETBUF_EN) /* If setbuf desired */
setbuf (fh,NULL); /* no buffering, please */
/* Seek to current write position */
if (fseek (fh,currPos,SEEK_SET))
{
slogFileErrorPrint ("SEEK",lc->fc.fileName);
S_UNLOCK_UTIL_RESOURCES ();
return;
}
}
else /* log file not opened, just copy it */
copy_named_files_ex (lc, newFile, lc->fc.fileName);
S_UNLOCK_UTIL_RESOURCES ();
}
/************************************************************************/
/* slogDeleteFile */
/************************************************************************/
ST_VOID slogDeleteFile (LOG_CTRL *lc)
{
S_GS_INIT ();
S_LOCK_UTIL_RESOURCES ();
/* first close the log file */
slogCloseFile (lc);
/* Now delete it */
remove (lc->fc.fileName);
S_UNLOCK_UTIL_RESOURCES ();
}
/************************************************************************/
/* findOldestMessage */
/************************************************************************/
static ST_LONG findOldestMessage (LOG_CTRL *lc, FILE *fh)
{
ST_CHAR idxFileName[S_MAX_PATH];
FILE *idxFh;
ST_CHAR buf[200];
ST_LONG startPos;
ST_LONG currPos;
ST_INT count;
ST_INT cmpLen;
cmpLen = strlen(OLDEST_STRING);
/* Need to find the start position by looking for the 'OLDEST' message. */
/* See if we have an index file and seek position ... */
if (slog_get_index_file_name (lc, idxFileName, sizeof(idxFileName)) == SD_SUCCESS)
{
idxFh = fopen (idxFileName,"r");
if (idxFh)
{
count = fscanf (idxFh, "%ld", &startPos);
fclose (idxFh);
if (count == 1)
{
if (fseek (fh, startPos, SEEK_SET) == 0)
{
fgets (buf,200,fh);
fgets (buf,200,fh);
fgets (buf,200,fh);
if (fgets (buf,200,fh))
{
if (buf[10] == 'O' && !strncmp (buf,OLDEST_STRING, cmpLen))
return (startPos);
}
}
}
}
}
/* Darn, need to start at the top and find it */
fseek (fh, 0, SEEK_SET);
while (SD_TRUE)
{
currPos = ftell (fh);
if (!fgets (buf,200,fh))
break;
chk_slog_service (lc);
/* Is this the position with the marker string? */
if (buf[10] == 'O' && !strncmp (buf,OLDEST_STRING, cmpLen))
return (currPos);
}
/* No oldest found, go to the start of the file */
fseek (fh, 0, SEEK_END);
currPos = ftell (fh);
return (currPos);
}
/************************************************************************/
/* slog_get_index_file_name */
/************************************************************************/
ST_RET slog_get_index_file_name (LOG_CTRL *lc, ST_CHAR *dest, ST_INT destLen)
{
ST_CHAR *src;
ST_INT srcLen;
src = lc->fc.fileName;
srcLen = strlen(src);
if (!src || srcLen == 0)
return (SD_FAILURE);
if (!dest || destLen < (srcLen+4)) /* +4 for len of ".sli" */
return (SD_FAILURE);
while (SD_TRUE)
{
*dest = *src;
if (*dest == 0) /* End of string ... */
break;
if (*dest == '.')
*dest = '_';
++src;
++dest;
}
strcat (dest, ".sli");
return (SD_SUCCESS);
}
/************************************************************************/
/* printStart */
/************************************************************************/
static ST_VOID printStart (FILE *fh)
{
time_t t;
t = time(NULL);
fprintf (fh,"\n\n***********************************************************");
fprintf (fh,"\n LOGGING STARTED %s", ctime(&t));
fprintf (fh,"***********************************************************");
}
/************************************************************************/
/* printWrap */
/************************************************************************/
static ST_VOID printWrap (FILE *fh)
{
time_t t;
t = time(NULL);
fprintf (fh,"\n***********************************************************");
fprintf (fh,"\n FILE WRAPPED %s", ctime(&t));
fprintf (fh,"***********************************************************");
}
/************************************************************************/
/* printWipe */
/************************************************************************/
static ST_VOID printWipe (FILE *fh)
{
fprintf (fh,"\n\n***********************************************************");
fprintf (fh,"\n%s",OLDEST_STRING);;
fprintf (fh,"\n***********************************************************\n\n");
}
/************************************************************************/
/* slogFileErrorPrint */
/************************************************************************/
static ST_VOID slogFileErrorPrint (ST_CHAR *text, ST_CHAR *fname)
{
fprintf (stderr,"\n*** LOG FILE %s ERROR (%s) : ",text,fname);
fprintf (stderr,"%s",strerror(errno));
}
/************************************************************************/
/* copy_named_files */
/************************************************************************/
#define FILE_READ_SIZE 1000
static ST_INT copy_named_files (LOG_CTRL *lc,
SD_CONST ST_CHAR *SD_CONST dest, SD_CONST ST_CHAR *SD_CONST src)
{
FILE *dest_fp;
FILE *src_fp;
ST_INT ret;
ST_CHAR buf[FILE_READ_SIZE+1];
ST_INT bytes_read;
ST_INT bytes_written;
if (!(src_fp = fopen (src,"rb")))
return (SD_FAILURE);
if (!(dest_fp = fopen (dest,"wb")))
{
fclose (src_fp);
return (SD_FAILURE);
}
ret = SD_SUCCESS;
while (SD_TRUE)
{
if (!(bytes_read = fread (buf,1,FILE_READ_SIZE,src_fp)))
break;
bytes_written = fwrite (buf,1,bytes_read,dest_fp);
if (bytes_read != bytes_written)
{
ret = SD_FAILURE;
break;
}
chk_slog_service (lc);
}
if (fclose (src_fp))
ret = SD_FAILURE;
if (fclose (dest_fp))
ret = SD_FAILURE;
return (ret);
}
/************************************************************************/
/* copy_named_files_ex */
/************************************************************************/
static ST_INT copy_named_files_ex (LOG_CTRL *lc, SD_CONST ST_CHAR *SD_CONST dest,
SD_CONST ST_CHAR *SD_CONST src)
{
FILE *dest_fp;
FILE *src_fp;
ST_INT ret;
ST_CHAR buf[200+1];
ST_LONG currPos;
ST_LONG oldestPos;
if (!(src_fp = fopen (src,"rb")))
return (SD_FAILURE);
oldestPos = findOldestMessage (lc, src_fp);
if (fseek (src_fp, oldestPos, SEEK_SET))
{
slogFileErrorPrint ("SEEK",lc->fc.fileName);
fclose (src_fp);
return (SD_FAILURE);
}
if (!(dest_fp = fopen (dest,"wb")))
{
fclose (src_fp);
return (SD_FAILURE);
}
ret = SD_SUCCESS;
while (SD_TRUE)
{
if (!fgets (buf,200,src_fp))
break;
fputs (buf,dest_fp);
chk_slog_service (lc);
}
if (fclose (src_fp))
ret = SD_FAILURE;
if (ret == SD_SUCCESS)
{
if (oldestPos > 0)
{
if (!(src_fp = fopen (src,"rb")))
{
fclose (dest_fp);
return (SD_FAILURE);
}
currPos = 0;
while (currPos < oldestPos)
{
if (!fgets (buf,200,src_fp))
break;
fputs (buf,dest_fp);
currPos = ftell (src_fp);
if (currPos == -1L)
{
slogFileErrorPrint ("TELL",lc->fc.fileName);
fclose (src_fp);
fclose (dest_fp);
return (SD_FAILURE);
}
chk_slog_service (lc);
}
}
}
if (fclose (src_fp))
ret = SD_FAILURE;
if (fclose (dest_fp))
ret = SD_FAILURE;
return (ret);
}
/************************************************************************/
/* chk_slog_service */
/************************************************************************/
static ST_INT slog_service_count;
static ST_VOID chk_slog_service (LOG_CTRL *lc)
{
ST_UINT32 logCtrlSave;
/* Allow the application to do it's thing during a slow operation */
if (slog_service_fun)
{
if (++slog_service_count > 10)
{
slog_service_count = 0;
/* do not allow file logging during this operation */
logCtrlSave = lc->logCtrl;
lc->logCtrl &= ~LOG_FILE_EN;
(*slog_service_fun) ();
lc->logCtrl = logCtrlSave;
}
}
}