Coverage Report

Created: 2026-03-04 06:13

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
  WINPR_ASSERT(appender);
43
0
  WINPR_ASSERT(filename);
44
45
0
  appender->FileName = _strdup(filename);
46
47
0
  return appender->FileName != nullptr;
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
  return appender->FilePath != nullptr;
55
0
}
56
57
static BOOL WLog_FileAppender_Open(wLog* log, wLogAppender* appender)
58
0
{
59
0
  wLogFileAppender* fileAppender = nullptr;
60
61
0
  if (!log || !appender)
62
0
    return FALSE;
63
64
0
  fileAppender = (wLogFileAppender*)appender;
65
66
0
  if (!fileAppender->FilePath)
67
0
  {
68
0
    fileAppender->FilePath = GetKnownSubPath(KNOWN_PATH_TEMP, "wlog");
69
70
0
    if (!fileAppender->FilePath)
71
0
      return FALSE;
72
0
  }
73
74
0
  if (!fileAppender->FileName)
75
0
  {
76
0
    fileAppender->FileName = (char*)malloc(MAX_PATH);
77
78
0
    if (!fileAppender->FileName)
79
0
      return FALSE;
80
81
0
    (void)sprintf_s(fileAppender->FileName, MAX_PATH, "%" PRIu32 ".log", GetCurrentProcessId());
82
0
  }
83
84
0
  if (!fileAppender->FullFileName)
85
0
  {
86
0
    fileAppender->FullFileName =
87
0
        GetCombinedPath(fileAppender->FilePath, fileAppender->FileName);
88
89
0
    if (!fileAppender->FullFileName)
90
0
      return FALSE;
91
0
  }
92
93
0
  if (!winpr_PathFileExists(fileAppender->FilePath))
94
0
  {
95
0
    if (!winpr_PathMakePath(fileAppender->FilePath, nullptr))
96
0
      return FALSE;
97
98
0
    UnixChangeFileMode(fileAppender->FilePath, 0xFFFF);
99
0
  }
100
101
0
  fileAppender->FileDescriptor = winpr_fopen(fileAppender->FullFileName, "a+");
102
103
0
  return fileAppender->FileDescriptor != nullptr;
104
0
}
105
106
static BOOL WLog_FileAppender_Close(wLog* log, wLogAppender* appender)
107
0
{
108
0
  wLogFileAppender* fileAppender = nullptr;
109
110
0
  if (!log || !appender)
111
0
    return FALSE;
112
113
0
  fileAppender = (wLogFileAppender*)appender;
114
115
0
  if (!fileAppender->FileDescriptor)
116
0
    return TRUE;
117
118
0
  (void)fclose(fileAppender->FileDescriptor);
119
0
  fileAppender->FileDescriptor = nullptr;
120
0
  return TRUE;
121
0
}
122
123
static BOOL WLog_FileAppender_WriteMessage(wLog* log, wLogAppender* appender,
124
                                           const wLogMessage* cmessage)
125
0
{
126
0
  if (!log || !appender || !cmessage)
127
0
    return FALSE;
128
129
0
  wLogFileAppender* fileAppender = (wLogFileAppender*)appender;
130
0
  FILE* fp = fileAppender->FileDescriptor;
131
132
0
  if (!fp)
133
0
    return FALSE;
134
135
0
  char prefix[WLOG_MAX_PREFIX_SIZE] = WINPR_C_ARRAY_INIT;
136
0
  WLog_Layout_GetMessagePrefix(log, appender->Layout, cmessage, prefix, sizeof(prefix));
137
0
  (void)fprintf(fp, "%s%s\n", prefix, cmessage->TextString);
138
0
  (void)fflush(fp); /* slow! */
139
0
  return TRUE;
140
0
}
141
142
static int g_DataId = 0;
143
144
static BOOL WLog_FileAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
145
                                               const wLogMessage* message)
146
0
{
147
0
  int DataId = 0;
148
0
  char* FullFileName = nullptr;
149
150
0
  if (!log || !appender || !message)
151
0
    return FALSE;
152
153
0
  DataId = g_DataId++;
154
0
  FullFileName = WLog_Message_GetOutputFileName(DataId, "dat");
155
0
  WLog_DataMessage_Write(FullFileName, message->Data, message->Length);
156
0
  free(FullFileName);
157
0
  return TRUE;
158
0
}
159
160
static int g_ImageId = 0;
161
162
static BOOL WLog_FileAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
163
                                                const wLogMessage* message)
164
0
{
165
0
  int ImageId = 0;
166
0
  char* FullFileName = nullptr;
167
168
0
  if (!log || !appender || !message)
169
0
    return FALSE;
170
171
0
  ImageId = g_ImageId++;
172
0
  FullFileName = WLog_Message_GetOutputFileName(ImageId, "bmp");
173
0
  WLog_ImageMessage_Write(FullFileName, message->ImageData, message->ImageWidth,
174
0
                          message->ImageHeight, message->ImageBpp);
175
0
  free(FullFileName);
176
0
  return TRUE;
177
0
}
178
179
static BOOL WLog_FileAppender_Set(wLogAppender* appender, const char* setting, void* value)
180
0
{
181
0
  wLogFileAppender* fileAppender = (wLogFileAppender*)appender;
182
183
  /* Just check the value string is not empty */
184
0
  if (!value || (strnlen(value, 2) == 0))
185
0
    return FALSE;
186
187
0
  if (!strcmp("outputfilename", setting))
188
0
    return WLog_FileAppender_SetOutputFileName(fileAppender, (const char*)value);
189
190
0
  if (!strcmp("outputfilepath", setting))
191
0
    return WLog_FileAppender_SetOutputFilePath(fileAppender, (const char*)value);
192
193
0
  return FALSE;
194
0
}
195
196
static void WLog_FileAppender_Free(wLogAppender* appender)
197
0
{
198
0
  wLogFileAppender* fileAppender = nullptr;
199
200
0
  if (appender)
201
0
  {
202
0
    fileAppender = (wLogFileAppender*)appender;
203
0
    free(fileAppender->FileName);
204
0
    free(fileAppender->FilePath);
205
0
    free(fileAppender->FullFileName);
206
0
    free(fileAppender);
207
0
  }
208
0
}
209
210
wLogAppender* WLog_FileAppender_New(WINPR_ATTR_UNUSED wLog* log)
211
0
{
212
0
  LPSTR env = nullptr;
213
0
  LPCSTR name = nullptr;
214
0
  DWORD nSize = 0;
215
0
  wLogFileAppender* FileAppender = nullptr;
216
0
  FileAppender = (wLogFileAppender*)calloc(1, sizeof(wLogFileAppender));
217
218
0
  if (!FileAppender)
219
0
    return nullptr;
220
221
0
  FileAppender->common.Type = WLOG_APPENDER_FILE;
222
0
  FileAppender->common.Open = WLog_FileAppender_Open;
223
0
  FileAppender->common.Close = WLog_FileAppender_Close;
224
0
  FileAppender->common.WriteMessage = WLog_FileAppender_WriteMessage;
225
0
  FileAppender->common.WriteDataMessage = WLog_FileAppender_WriteDataMessage;
226
0
  FileAppender->common.WriteImageMessage = WLog_FileAppender_WriteImageMessage;
227
0
  FileAppender->common.Free = WLog_FileAppender_Free;
228
0
  FileAppender->common.Set = WLog_FileAppender_Set;
229
0
  name = "WLOG_FILEAPPENDER_OUTPUT_FILE_PATH";
230
0
  nSize = GetEnvironmentVariableA(name, nullptr, 0);
231
232
0
  if (nSize)
233
0
  {
234
0
    BOOL status = 0;
235
0
    env = (LPSTR)malloc(nSize);
236
237
0
    if (!env)
238
0
      goto error_free;
239
240
0
    if (GetEnvironmentVariableA(name, env, nSize) != nSize - 1)
241
0
    {
242
0
      free(env);
243
0
      goto error_free;
244
0
    }
245
246
0
    status = WLog_FileAppender_SetOutputFilePath(FileAppender, env);
247
0
    free(env);
248
249
0
    if (!status)
250
0
      goto error_free;
251
0
  }
252
253
0
  name = "WLOG_FILEAPPENDER_OUTPUT_FILE_NAME";
254
0
  nSize = GetEnvironmentVariableA(name, nullptr, 0);
255
256
0
  if (nSize)
257
0
  {
258
0
    BOOL status = FALSE;
259
0
    env = (LPSTR)malloc(nSize);
260
261
0
    if (!env)
262
0
      goto error_output_file_name;
263
264
0
    if (GetEnvironmentVariableA(name, env, nSize) == nSize - 1)
265
0
      status = WLog_FileAppender_SetOutputFileName(FileAppender, env);
266
0
    free(env);
267
268
0
    if (!status)
269
0
      goto error_output_file_name;
270
0
  }
271
272
0
  return (wLogAppender*)FileAppender;
273
0
error_output_file_name:
274
0
  free(FileAppender->FilePath);
275
0
error_free:
276
0
  free(FileAppender);
277
0
  return nullptr;
278
0
}