Coverage Report

Created: 2025-11-24 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/winpr/libwinpr/utils/wlog/FileAppender.c
Line
Count
Source
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
  wLogAppender 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,
130
                                           const wLogMessage* cmessage)
131
0
{
132
0
  if (!log || !appender || !cmessage)
133
0
    return FALSE;
134
135
0
  wLogFileAppender* fileAppender = (wLogFileAppender*)appender;
136
0
  FILE* fp = fileAppender->FileDescriptor;
137
138
0
  if (!fp)
139
0
    return FALSE;
140
141
0
  char prefix[WLOG_MAX_PREFIX_SIZE] = { 0 };
142
0
  WLog_Layout_GetMessagePrefix(log, appender->Layout, cmessage, prefix, sizeof(prefix));
143
0
  (void)fprintf(fp, "%s%s\n", prefix, cmessage->TextString);
144
0
  (void)fflush(fp); /* slow! */
145
0
  return TRUE;
146
0
}
147
148
static int g_DataId = 0;
149
150
static BOOL WLog_FileAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
151
                                               const wLogMessage* message)
152
0
{
153
0
  int DataId = 0;
154
0
  char* FullFileName = NULL;
155
156
0
  if (!log || !appender || !message)
157
0
    return FALSE;
158
159
0
  DataId = g_DataId++;
160
0
  FullFileName = WLog_Message_GetOutputFileName(DataId, "dat");
161
0
  WLog_DataMessage_Write(FullFileName, message->Data, message->Length);
162
0
  free(FullFileName);
163
0
  return TRUE;
164
0
}
165
166
static int g_ImageId = 0;
167
168
static BOOL WLog_FileAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
169
                                                const wLogMessage* message)
170
0
{
171
0
  int ImageId = 0;
172
0
  char* FullFileName = NULL;
173
174
0
  if (!log || !appender || !message)
175
0
    return FALSE;
176
177
0
  ImageId = g_ImageId++;
178
0
  FullFileName = WLog_Message_GetOutputFileName(ImageId, "bmp");
179
0
  WLog_ImageMessage_Write(FullFileName, message->ImageData, message->ImageWidth,
180
0
                          message->ImageHeight, message->ImageBpp);
181
0
  free(FullFileName);
182
0
  return TRUE;
183
0
}
184
185
static BOOL WLog_FileAppender_Set(wLogAppender* appender, const char* setting, void* value)
186
0
{
187
0
  wLogFileAppender* fileAppender = (wLogFileAppender*)appender;
188
189
  /* Just check the value string is not empty */
190
0
  if (!value || (strnlen(value, 2) == 0))
191
0
    return FALSE;
192
193
0
  if (!strcmp("outputfilename", setting))
194
0
    return WLog_FileAppender_SetOutputFileName(fileAppender, (const char*)value);
195
196
0
  if (!strcmp("outputfilepath", setting))
197
0
    return WLog_FileAppender_SetOutputFilePath(fileAppender, (const char*)value);
198
199
0
  return FALSE;
200
0
}
201
202
static void WLog_FileAppender_Free(wLogAppender* appender)
203
0
{
204
0
  wLogFileAppender* fileAppender = NULL;
205
206
0
  if (appender)
207
0
  {
208
0
    fileAppender = (wLogFileAppender*)appender;
209
0
    free(fileAppender->FileName);
210
0
    free(fileAppender->FilePath);
211
0
    free(fileAppender->FullFileName);
212
0
    free(fileAppender);
213
0
  }
214
0
}
215
216
wLogAppender* WLog_FileAppender_New(WINPR_ATTR_UNUSED wLog* log)
217
0
{
218
0
  LPSTR env = NULL;
219
0
  LPCSTR name = NULL;
220
0
  DWORD nSize = 0;
221
0
  wLogFileAppender* FileAppender = NULL;
222
0
  FileAppender = (wLogFileAppender*)calloc(1, sizeof(wLogFileAppender));
223
224
0
  if (!FileAppender)
225
0
    return NULL;
226
227
0
  FileAppender->common.Type = WLOG_APPENDER_FILE;
228
0
  FileAppender->common.Open = WLog_FileAppender_Open;
229
0
  FileAppender->common.Close = WLog_FileAppender_Close;
230
0
  FileAppender->common.WriteMessage = WLog_FileAppender_WriteMessage;
231
0
  FileAppender->common.WriteDataMessage = WLog_FileAppender_WriteDataMessage;
232
0
  FileAppender->common.WriteImageMessage = WLog_FileAppender_WriteImageMessage;
233
0
  FileAppender->common.Free = WLog_FileAppender_Free;
234
0
  FileAppender->common.Set = WLog_FileAppender_Set;
235
0
  name = "WLOG_FILEAPPENDER_OUTPUT_FILE_PATH";
236
0
  nSize = GetEnvironmentVariableA(name, NULL, 0);
237
238
0
  if (nSize)
239
0
  {
240
0
    BOOL status = 0;
241
0
    env = (LPSTR)malloc(nSize);
242
243
0
    if (!env)
244
0
      goto error_free;
245
246
0
    if (GetEnvironmentVariableA(name, env, nSize) != nSize - 1)
247
0
    {
248
0
      free(env);
249
0
      goto error_free;
250
0
    }
251
252
0
    status = WLog_FileAppender_SetOutputFilePath(FileAppender, env);
253
0
    free(env);
254
255
0
    if (!status)
256
0
      goto error_free;
257
0
  }
258
259
0
  name = "WLOG_FILEAPPENDER_OUTPUT_FILE_NAME";
260
0
  nSize = GetEnvironmentVariableA(name, NULL, 0);
261
262
0
  if (nSize)
263
0
  {
264
0
    BOOL status = FALSE;
265
0
    env = (LPSTR)malloc(nSize);
266
267
0
    if (!env)
268
0
      goto error_output_file_name;
269
270
0
    if (GetEnvironmentVariableA(name, env, nSize) == nSize - 1)
271
0
      status = WLog_FileAppender_SetOutputFileName(FileAppender, env);
272
0
    free(env);
273
274
0
    if (!status)
275
0
      goto error_output_file_name;
276
0
  }
277
278
0
  return (wLogAppender*)FileAppender;
279
0
error_output_file_name:
280
0
  free(FileAppender->FilePath);
281
0
error_free:
282
0
  free(FileAppender);
283
  return NULL;
284
0
}