Blame winpr/libwinpr/utils/wlog/FileAppender.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * WinPR: Windows Portable Runtime
Packit 1fb8d4
 * WinPR Logger
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include "FileAppender.h"
Packit 1fb8d4
#include "Message.h"
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/environment.h>
Packit 1fb8d4
#include <winpr/file.h>
Packit 1fb8d4
#include <winpr/path.h>
Packit 1fb8d4
Packit 1fb8d4
struct _wLogFileAppender
Packit 1fb8d4
{
Packit 1fb8d4
	WLOG_APPENDER_COMMON();
Packit 1fb8d4
Packit 1fb8d4
	char* FileName;
Packit 1fb8d4
	char* FilePath;
Packit 1fb8d4
	char* FullFileName;
Packit 1fb8d4
	FILE* FileDescriptor;
Packit 1fb8d4
};
Packit 1fb8d4
typedef struct _wLogFileAppender wLogFileAppender;
Packit 1fb8d4
Packit 1fb8d4
static BOOL WLog_FileAppender_SetOutputFileName(wLogFileAppender* appender, const char* filename)
Packit 1fb8d4
{
Packit 1fb8d4
	appender->FileName = _strdup(filename);
Packit 1fb8d4
Packit 1fb8d4
	if (!appender->FileName)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL WLog_FileAppender_SetOutputFilePath(wLogFileAppender* appender, const char* filepath)
Packit 1fb8d4
{
Packit 1fb8d4
	appender->FilePath = _strdup(filepath);
Packit 1fb8d4
Packit 1fb8d4
	if (!appender->FilePath)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL WLog_FileAppender_Open(wLog* log, wLogAppender* appender)
Packit 1fb8d4
{
Packit 1fb8d4
	wLogFileAppender* fileAppender;
Packit 1fb8d4
Packit 1fb8d4
	if (!log || !appender)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	fileAppender = (wLogFileAppender*)appender;
Packit 1fb8d4
Packit 1fb8d4
	if (!fileAppender->FilePath)
Packit 1fb8d4
	{
Packit 1fb8d4
		fileAppender->FilePath = GetKnownSubPath(KNOWN_PATH_TEMP, "wlog");
Packit 1fb8d4
Packit 1fb8d4
		if (!fileAppender->FilePath)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!fileAppender->FileName)
Packit 1fb8d4
	{
Packit Service 5a9772
		fileAppender->FileName = (char*)malloc(MAX_PATH);
Packit 1fb8d4
Packit 1fb8d4
		if (!fileAppender->FileName)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit Service 5a9772
		sprintf_s(fileAppender->FileName, MAX_PATH, "%" PRIu32 ".log", GetCurrentProcessId());
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!fileAppender->FullFileName)
Packit 1fb8d4
	{
Packit Service 5a9772
		fileAppender->FullFileName =
Packit Service 5a9772
		    GetCombinedPath(fileAppender->FilePath, fileAppender->FileName);
Packit 1fb8d4
Packit 1fb8d4
		if (!fileAppender->FullFileName)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!PathFileExistsA(fileAppender->FilePath))
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!PathMakePathA(fileAppender->FilePath, 0))
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		UnixChangeFileMode(fileAppender->FilePath, 0xFFFF);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	fileAppender->FileDescriptor = fopen(fileAppender->FullFileName, "a+");
Packit 1fb8d4
Packit 1fb8d4
	if (!fileAppender->FileDescriptor)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL WLog_FileAppender_Close(wLog* log, wLogAppender* appender)
Packit 1fb8d4
{
Packit 1fb8d4
	wLogFileAppender* fileAppender;
Packit 1fb8d4
Packit 1fb8d4
	if (!log || !appender)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	fileAppender = (wLogFileAppender*)appender;
Packit 1fb8d4
Packit 1fb8d4
	if (!fileAppender->FileDescriptor)
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	fclose(fileAppender->FileDescriptor);
Packit 1fb8d4
	fileAppender->FileDescriptor = NULL;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL WLog_FileAppender_WriteMessage(wLog* log, wLogAppender* appender, wLogMessage* message)
Packit 1fb8d4
{
Packit 1fb8d4
	FILE* fp;
Packit 1fb8d4
	char prefix[WLOG_MAX_PREFIX_SIZE];
Packit 1fb8d4
	wLogFileAppender* fileAppender;
Packit 1fb8d4
Packit 1fb8d4
	if (!log || !appender || !message)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	fileAppender = (wLogFileAppender*)appender;
Packit 1fb8d4
	fp = fileAppender->FileDescriptor;
Packit 1fb8d4
Packit 1fb8d4
	if (!fp)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	message->PrefixString = prefix;
Packit 1fb8d4
	WLog_Layout_GetMessagePrefix(log, appender->Layout, message);
Packit 1fb8d4
	fprintf(fp, "%s%s\n", message->PrefixString, message->TextString);
Packit 1fb8d4
	fflush(fp); /* slow! */
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int g_DataId = 0;
Packit 1fb8d4
Packit 1fb8d4
static BOOL WLog_FileAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
Packit Service 5a9772
                                               wLogMessage* message)
Packit 1fb8d4
{
Packit 1fb8d4
	int DataId;
Packit 1fb8d4
	char* FullFileName;
Packit 1fb8d4
Packit 1fb8d4
	if (!log || !appender || !message)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	DataId = g_DataId++;
Packit 1fb8d4
	FullFileName = WLog_Message_GetOutputFileName(DataId, "dat");
Packit 1fb8d4
	WLog_DataMessage_Write(FullFileName, message->Data, message->Length);
Packit 1fb8d4
	free(FullFileName);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int g_ImageId = 0;
Packit 1fb8d4
Packit 1fb8d4
static BOOL WLog_FileAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
Packit Service 5a9772
                                                wLogMessage* message)
Packit 1fb8d4
{
Packit 1fb8d4
	int ImageId;
Packit 1fb8d4
	char* FullFileName;
Packit 1fb8d4
Packit 1fb8d4
	if (!log || !appender || !message)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	ImageId = g_ImageId++;
Packit 1fb8d4
	FullFileName = WLog_Message_GetOutputFileName(ImageId, "bmp");
Packit Service 5a9772
	WLog_ImageMessage_Write(FullFileName, message->ImageData, message->ImageWidth,
Packit Service 5a9772
	                        message->ImageHeight, message->ImageBpp);
Packit 1fb8d4
	free(FullFileName);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL WLog_FileAppender_Set(wLogAppender* appender, const char* setting, void* value)
Packit 1fb8d4
{
Packit Service 5a9772
	wLogFileAppender* fileAppender = (wLogFileAppender*)appender;
Packit 1fb8d4
Packit Service 5a9772
	/* Just check the value string is not empty */
Packit Service 5a9772
	if (!value || (strnlen(value, 2) == 0))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!strcmp("outputfilename", setting))
Packit 1fb8d4
		return WLog_FileAppender_SetOutputFileName(fileAppender, (const char*)value);
Packit 1fb8d4
	else if (!strcmp("outputfilepath", setting))
Packit 1fb8d4
		return WLog_FileAppender_SetOutputFilePath(fileAppender, (const char*)value);
Packit 1fb8d4
	else
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void WLog_FileAppender_Free(wLogAppender* appender)
Packit 1fb8d4
{
Packit 1fb8d4
	wLogFileAppender* fileAppender = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (appender)
Packit 1fb8d4
	{
Packit 1fb8d4
		fileAppender = (wLogFileAppender*)appender;
Packit 1fb8d4
		free(fileAppender->FileName);
Packit 1fb8d4
		free(fileAppender->FilePath);
Packit 1fb8d4
		free(fileAppender->FullFileName);
Packit 1fb8d4
		free(fileAppender);
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
wLogAppender* WLog_FileAppender_New(wLog* log)
Packit 1fb8d4
{
Packit 1fb8d4
	LPSTR env;
Packit 1fb8d4
	LPCSTR name;
Packit 1fb8d4
	DWORD nSize;
Packit 1fb8d4
	wLogFileAppender* FileAppender;
Packit Service 5a9772
	FileAppender = (wLogFileAppender*)calloc(1, sizeof(wLogFileAppender));
Packit 1fb8d4
Packit 1fb8d4
	if (!FileAppender)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	FileAppender->Type = WLOG_APPENDER_FILE;
Packit 1fb8d4
	FileAppender->Open = WLog_FileAppender_Open;
Packit 1fb8d4
	FileAppender->Close = WLog_FileAppender_Close;
Packit 1fb8d4
	FileAppender->WriteMessage = WLog_FileAppender_WriteMessage;
Packit 1fb8d4
	FileAppender->WriteDataMessage = WLog_FileAppender_WriteDataMessage;
Packit 1fb8d4
	FileAppender->WriteImageMessage = WLog_FileAppender_WriteImageMessage;
Packit 1fb8d4
	FileAppender->Free = WLog_FileAppender_Free;
Packit 1fb8d4
	FileAppender->Set = WLog_FileAppender_Set;
Packit 1fb8d4
	name = "WLOG_FILEAPPENDER_OUTPUT_FILE_PATH";
Packit 1fb8d4
	nSize = GetEnvironmentVariableA(name, NULL, 0);
Packit 1fb8d4
Packit 1fb8d4
	if (nSize)
Packit 1fb8d4
	{
Packit 1fb8d4
		BOOL status;
Packit Service 5a9772
		env = (LPSTR)malloc(nSize);
Packit 1fb8d4
Packit 1fb8d4
		if (!env)
Packit 1fb8d4
			goto error_free;
Packit 1fb8d4
Packit 1fb8d4
		if (GetEnvironmentVariableA(name, env, nSize) != nSize - 1)
Packit 1fb8d4
		{
Packit 1fb8d4
			free(env);
Packit 1fb8d4
			goto error_free;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		status = WLog_FileAppender_SetOutputFilePath(FileAppender, env);
Packit 1fb8d4
		free(env);
Packit 1fb8d4
Packit 1fb8d4
		if (!status)
Packit 1fb8d4
			goto error_free;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	name = "WLOG_FILEAPPENDER_OUTPUT_FILE_NAME";
Packit 1fb8d4
	nSize = GetEnvironmentVariableA(name, NULL, 0);
Packit 1fb8d4
Packit 1fb8d4
	if (nSize)
Packit 1fb8d4
	{
Packit 1fb8d4
		BOOL status = FALSE;
Packit Service 5a9772
		env = (LPSTR)malloc(nSize);
Packit 1fb8d4
Packit 1fb8d4
		if (!env)
Packit 1fb8d4
			goto error_output_file_name;
Packit 1fb8d4
Packit 1fb8d4
		if (GetEnvironmentVariableA(name, env, nSize) == nSize - 1)
Packit 1fb8d4
			status = WLog_FileAppender_SetOutputFileName(FileAppender, env);
Packit 1fb8d4
		free(env);
Packit 1fb8d4
Packit 1fb8d4
		if (!status)
Packit 1fb8d4
			goto error_output_file_name;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return (wLogAppender*)FileAppender;
Packit 1fb8d4
error_output_file_name:
Packit 1fb8d4
	free(FileAppender->FilePath);
Packit 1fb8d4
error_free:
Packit 1fb8d4
	free(FileAppender);
Packit 1fb8d4
	return NULL;
Packit 1fb8d4
}