Coverage Report

Created: 2025-07-01 06:46

/src/FreeRDP/winpr/libwinpr/utils/wlog/FileAppender.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * WinPR: Windows Portable Runtime
3
 * WinPR Logger
4
 *
5
 * Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
20
#include <winpr/config.h>
21
22
#include "FileAppender.h"
23
#include "Message.h"
24
25
#include <winpr/crt.h>
26
#include <winpr/environment.h>
27
#include <winpr/file.h>
28
#include <winpr/path.h>
29
30
typedef struct
31
{
32
  WLOG_APPENDER_COMMON();
33
34
  char* FileName;
35
  char* FilePath;
36
  char* FullFileName;
37
  FILE* FileDescriptor;
38
} wLogFileAppender;
39
40
static BOOL WLog_FileAppender_SetOutputFileName(wLogFileAppender* appender, const char* filename)
41
0
{
42
0
  appender->FileName = _strdup(filename);
43
44
0
  if (!appender->FileName)
45
0
    return FALSE;
46
47
0
  return TRUE;
48
0
}
49
50
static BOOL WLog_FileAppender_SetOutputFilePath(wLogFileAppender* appender, const char* filepath)
51
0
{
52
0
  appender->FilePath = _strdup(filepath);
53
54
0
  if (!appender->FilePath)
55
0
    return FALSE;
56
57
0
  return TRUE;
58
0
}
59
60
static BOOL WLog_FileAppender_Open(wLog* log, wLogAppender* appender)
61
0
{
62
0
  wLogFileAppender* fileAppender = NULL;
63
64
0
  if (!log || !appender)
65
0
    return FALSE;
66
67
0
  fileAppender = (wLogFileAppender*)appender;
68
69
0
  if (!fileAppender->FilePath)
70
0
  {
71
0
    fileAppender->FilePath = GetKnownSubPath(KNOWN_PATH_TEMP, "wlog");
72
73
0
    if (!fileAppender->FilePath)
74
0
      return FALSE;
75
0
  }
76
77
0
  if (!fileAppender->FileName)
78
0
  {
79
0
    fileAppender->FileName = (char*)malloc(MAX_PATH);
80
81
0
    if (!fileAppender->FileName)
82
0
      return FALSE;
83
84
0
    (void)sprintf_s(fileAppender->FileName, MAX_PATH, "%" PRIu32 ".log", GetCurrentProcessId());
85
0
  }
86
87
0
  if (!fileAppender->FullFileName)
88
0
  {
89
0
    fileAppender->FullFileName =
90
0
        GetCombinedPath(fileAppender->FilePath, fileAppender->FileName);
91
92
0
    if (!fileAppender->FullFileName)
93
0
      return FALSE;
94
0
  }
95
96
0
  if (!winpr_PathFileExists(fileAppender->FilePath))
97
0
  {
98
0
    if (!winpr_PathMakePath(fileAppender->FilePath, 0))
99
0
      return FALSE;
100
101
0
    UnixChangeFileMode(fileAppender->FilePath, 0xFFFF);
102
0
  }
103
104
0
  fileAppender->FileDescriptor = winpr_fopen(fileAppender->FullFileName, "a+");
105
106
0
  if (!fileAppender->FileDescriptor)
107
0
    return FALSE;
108
109
0
  return TRUE;
110
0
}
111
112
static BOOL WLog_FileAppender_Close(wLog* log, wLogAppender* appender)
113
0
{
114
0
  wLogFileAppender* fileAppender = NULL;
115
116
0
  if (!log || !appender)
117
0
    return FALSE;
118
119
0
  fileAppender = (wLogFileAppender*)appender;
120
121
0
  if (!fileAppender->FileDescriptor)
122
0
    return TRUE;
123
124
0
  (void)fclose(fileAppender->FileDescriptor);
125
0
  fileAppender->FileDescriptor = NULL;
126
0
  return TRUE;
127
0
}
128
129
static BOOL WLog_FileAppender_WriteMessage(wLog* log, wLogAppender* appender, wLogMessage* message)
130
0
{
131
0
  FILE* fp = NULL;
132
0
  char prefix[WLOG_MAX_PREFIX_SIZE] = { 0 };
133
0
  wLogFileAppender* fileAppender = NULL;
134
135
0
  if (!log || !appender || !message)
136
0
    return FALSE;
137
138
0
  fileAppender = (wLogFileAppender*)appender;
139
0
  fp = fileAppender->FileDescriptor;
140
141
0
  if (!fp)
142
0
    return FALSE;
143
144
0
  message->PrefixString = prefix;
145
0
  WLog_Layout_GetMessagePrefix(log, appender->Layout, message);
146
0
  (void)fprintf(fp, "%s%s\n", message->PrefixString, message->TextString);
147
0
  (void)fflush(fp); /* slow! */
148
0
  return TRUE;
149
0
}
150
151
static int g_DataId = 0;
152
153
static BOOL WLog_FileAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
154
                                               wLogMessage* message)
155
0
{
156
0
  int DataId = 0;
157
0
  char* FullFileName = NULL;
158
159
0
  if (!log || !appender || !message)
160
0
    return FALSE;
161
162
0
  DataId = g_DataId++;
163
0
  FullFileName = WLog_Message_GetOutputFileName(DataId, "dat");
164
0
  WLog_DataMessage_Write(FullFileName, message->Data, message->Length);
165
0
  free(FullFileName);
166
0
  return TRUE;
167
0
}
168
169
static int g_ImageId = 0;
170
171
static BOOL WLog_FileAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
172
                                                wLogMessage* message)
173
0
{
174
0
  int ImageId = 0;
175
0
  char* FullFileName = NULL;
176
177
0
  if (!log || !appender || !message)
178
0
    return FALSE;
179
180
0
  ImageId = g_ImageId++;
181
0
  FullFileName = WLog_Message_GetOutputFileName(ImageId, "bmp");
182
0
  WLog_ImageMessage_Write(FullFileName, message->ImageData, message->ImageWidth,
183
0
                          message->ImageHeight, message->ImageBpp);
184
0
  free(FullFileName);
185
0
  return TRUE;
186
0
}
187
188
static BOOL WLog_FileAppender_Set(wLogAppender* appender, const char* setting, void* value)
189
0
{
190
0
  wLogFileAppender* fileAppender = (wLogFileAppender*)appender;
191
192
  /* Just check the value string is not empty */
193
0
  if (!value || (strnlen(value, 2) == 0))
194
0
    return FALSE;
195
196
0
  if (!strcmp("outputfilename", setting))
197
0
    return WLog_FileAppender_SetOutputFileName(fileAppender, (const char*)value);
198
199
0
  if (!strcmp("outputfilepath", setting))
200
0
    return WLog_FileAppender_SetOutputFilePath(fileAppender, (const char*)value);
201
202
0
  return FALSE;
203
0
}
204
205
static void WLog_FileAppender_Free(wLogAppender* appender)
206
0
{
207
0
  wLogFileAppender* fileAppender = NULL;
208
209
0
  if (appender)
210
0
  {
211
0
    fileAppender = (wLogFileAppender*)appender;
212
0
    free(fileAppender->FileName);
213
0
    free(fileAppender->FilePath);
214
0
    free(fileAppender->FullFileName);
215
0
    free(fileAppender);
216
0
  }
217
0
}
218
219
wLogAppender* WLog_FileAppender_New(WINPR_ATTR_UNUSED wLog* log)
220
0
{
221
0
  LPSTR env = NULL;
222
0
  LPCSTR name = NULL;
223
0
  DWORD nSize = 0;
224
0
  wLogFileAppender* FileAppender = NULL;
225
0
  FileAppender = (wLogFileAppender*)calloc(1, sizeof(wLogFileAppender));
226
227
0
  if (!FileAppender)
228
0
    return NULL;
229
230
0
  FileAppender->Type = WLOG_APPENDER_FILE;
231
0
  FileAppender->Open = WLog_FileAppender_Open;
232
0
  FileAppender->Close = WLog_FileAppender_Close;
233
0
  FileAppender->WriteMessage = WLog_FileAppender_WriteMessage;
234
0
  FileAppender->WriteDataMessage = WLog_FileAppender_WriteDataMessage;
235
0
  FileAppender->WriteImageMessage = WLog_FileAppender_WriteImageMessage;
236
0
  FileAppender->Free = WLog_FileAppender_Free;
237
0
  FileAppender->Set = WLog_FileAppender_Set;
238
0
  name = "WLOG_FILEAPPENDER_OUTPUT_FILE_PATH";
239
0
  nSize = GetEnvironmentVariableA(name, NULL, 0);
240
241
0
  if (nSize)
242
0
  {
243
0
    BOOL status = 0;
244
0
    env = (LPSTR)malloc(nSize);
245
246
0
    if (!env)
247
0
      goto error_free;
248
249
0
    if (GetEnvironmentVariableA(name, env, nSize) != nSize - 1)
250
0
    {
251
0
      free(env);
252
0
      goto error_free;
253
0
    }
254
255
0
    status = WLog_FileAppender_SetOutputFilePath(FileAppender, env);
256
0
    free(env);
257
258
0
    if (!status)
259
0
      goto error_free;
260
0
  }
261
262
0
  name = "WLOG_FILEAPPENDER_OUTPUT_FILE_NAME";
263
0
  nSize = GetEnvironmentVariableA(name, NULL, 0);
264
265
0
  if (nSize)
266
0
  {
267
0
    BOOL status = FALSE;
268
0
    env = (LPSTR)malloc(nSize);
269
270
0
    if (!env)
271
0
      goto error_output_file_name;
272
273
0
    if (GetEnvironmentVariableA(name, env, nSize) == nSize - 1)
274
0
      status = WLog_FileAppender_SetOutputFileName(FileAppender, env);
275
0
    free(env);
276
277
0
    if (!status)
278
0
      goto error_output_file_name;
279
0
  }
280
281
0
  return (wLogAppender*)FileAppender;
282
0
error_output_file_name:
283
0
  free(FileAppender->FilePath);
284
0
error_free:
285
0
  free(FileAppender);
286
0
  return NULL;
287
0
}