Coverage Report

Created: 2024-05-20 06:11

/src/FreeRDP/winpr/libwinpr/file/namedPipeClient.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * WinPR: Windows Portable Runtime
3
 * File Functions
4
 *
5
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 * Copyright 2014 Hewlett-Packard Development Company, L.P.
7
 * Copyright 2015 Thincast Technologies GmbH
8
 * Copyright 2015 bernhard.miklautz@thincast.com
9
 * Licensed under the Apache License, Version 2.0 (the "License");
10
 * you may not use this file except in compliance with the License.
11
 * You may obtain a copy of the License at
12
 *
13
 *     http://www.apache.org/licenses/LICENSE-2.0
14
 *
15
 * Unless required by applicable law or agreed to in writing, software
16
 * distributed under the License is distributed on an "AS IS" BASIS,
17
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
 * See the License for the specific language governing permissions and
19
 * limitations under the License.
20
 */
21
22
#include <winpr/config.h>
23
24
#include <winpr/crt.h>
25
#include <winpr/path.h>
26
#include <winpr/file.h>
27
28
#ifdef WINPR_HAVE_UNISTD_H
29
#include <unistd.h>
30
#endif
31
32
#include "../log.h"
33
#define TAG WINPR_TAG("file")
34
35
#ifndef _WIN32
36
37
#ifdef ANDROID
38
#include <sys/vfs.h>
39
#else
40
#include <sys/statvfs.h>
41
#endif
42
43
#include "../handle/handle.h"
44
45
#include "../pipe/pipe.h"
46
47
static HANDLE_CREATOR _NamedPipeClientHandleCreator;
48
49
static BOOL NamedPipeClientIsHandled(HANDLE handle)
50
0
{
51
0
  return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_NAMED_PIPE, TRUE);
52
0
}
53
54
static BOOL NamedPipeClientCloseHandle(HANDLE handle)
55
0
{
56
0
  WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)handle;
57
58
0
  if (!NamedPipeClientIsHandled(handle))
59
0
    return FALSE;
60
61
0
  if (pNamedPipe->clientfd != -1)
62
0
  {
63
    // WLOG_DBG(TAG, "closing clientfd %d", pNamedPipe->clientfd);
64
0
    close(pNamedPipe->clientfd);
65
0
  }
66
67
0
  if (pNamedPipe->serverfd != -1)
68
0
  {
69
    // WLOG_DBG(TAG, "closing serverfd %d", pNamedPipe->serverfd);
70
0
    close(pNamedPipe->serverfd);
71
0
  }
72
73
0
  if (pNamedPipe->pfnUnrefNamedPipe)
74
0
    pNamedPipe->pfnUnrefNamedPipe(pNamedPipe);
75
76
0
  free(pNamedPipe->lpFileName);
77
0
  free(pNamedPipe->lpFilePath);
78
0
  free(pNamedPipe->name);
79
0
  free(pNamedPipe);
80
0
  return TRUE;
81
0
}
82
83
static int NamedPipeClientGetFd(HANDLE handle)
84
0
{
85
0
  WINPR_NAMED_PIPE* file = (WINPR_NAMED_PIPE*)handle;
86
87
0
  if (!NamedPipeClientIsHandled(handle))
88
0
    return -1;
89
90
0
  if (file->ServerMode)
91
0
    return file->serverfd;
92
0
  else
93
0
    return file->clientfd;
94
0
}
95
96
static HANDLE_OPS ops = {
97
  NamedPipeClientIsHandled,
98
  NamedPipeClientCloseHandle,
99
  NamedPipeClientGetFd,
100
  NULL, /* CleanupHandle */
101
  NamedPipeRead,
102
  NULL, /* FileReadEx */
103
  NULL, /* FileReadScatter */
104
  NamedPipeWrite,
105
  NULL, /* FileWriteEx */
106
  NULL, /* FileWriteGather */
107
  NULL, /* FileGetFileSize */
108
  NULL, /*  FlushFileBuffers */
109
  NULL, /* FileSetEndOfFile */
110
  NULL, /* FileSetFilePointer */
111
  NULL, /* SetFilePointerEx */
112
  NULL, /* FileLockFile */
113
  NULL, /* FileLockFileEx */
114
  NULL, /* FileUnlockFile */
115
  NULL, /* FileUnlockFileEx */
116
  NULL, /* SetFileTime */
117
  NULL, /* FileGetFileInformationByHandle */
118
};
119
120
static HANDLE NamedPipeClientCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess,
121
                                         DWORD dwShareMode,
122
                                         LPSECURITY_ATTRIBUTES lpSecurityAttributes,
123
                                         DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
124
                                         HANDLE hTemplateFile)
125
0
{
126
0
  char* name = NULL;
127
0
  int status = 0;
128
0
  HANDLE hNamedPipe = NULL;
129
0
  struct sockaddr_un s = { 0 };
130
0
  WINPR_NAMED_PIPE* pNamedPipe = NULL;
131
132
0
  if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
133
0
  {
134
0
    WLog_ERR(TAG, "WinPR does not support the FILE_FLAG_OVERLAPPED flag");
135
0
    SetLastError(ERROR_NOT_SUPPORTED);
136
0
    return INVALID_HANDLE_VALUE;
137
0
  }
138
139
0
  if (!lpFileName)
140
0
    return INVALID_HANDLE_VALUE;
141
142
0
  if (!IsNamedPipeFileNameA(lpFileName))
143
0
    return INVALID_HANDLE_VALUE;
144
145
0
  name = GetNamedPipeNameWithoutPrefixA(lpFileName);
146
147
0
  if (!name)
148
0
    return INVALID_HANDLE_VALUE;
149
150
0
  free(name);
151
0
  pNamedPipe = (WINPR_NAMED_PIPE*)calloc(1, sizeof(WINPR_NAMED_PIPE));
152
153
0
  if (!pNamedPipe)
154
0
  {
155
0
    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
156
0
    return INVALID_HANDLE_VALUE;
157
0
  }
158
159
0
  hNamedPipe = (HANDLE)pNamedPipe;
160
0
  WINPR_HANDLE_SET_TYPE_AND_MODE(pNamedPipe, HANDLE_TYPE_NAMED_PIPE, WINPR_FD_READ);
161
0
  pNamedPipe->name = _strdup(lpFileName);
162
163
0
  if (!pNamedPipe->name)
164
0
  {
165
0
    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
166
0
    free(pNamedPipe);
167
0
    return INVALID_HANDLE_VALUE;
168
0
  }
169
170
0
  pNamedPipe->dwOpenMode = 0;
171
0
  pNamedPipe->dwPipeMode = 0;
172
0
  pNamedPipe->nMaxInstances = 0;
173
0
  pNamedPipe->nOutBufferSize = 0;
174
0
  pNamedPipe->nInBufferSize = 0;
175
0
  pNamedPipe->nDefaultTimeOut = 0;
176
0
  pNamedPipe->dwFlagsAndAttributes = dwFlagsAndAttributes;
177
0
  pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpFileName);
178
179
0
  if (!pNamedPipe->lpFileName)
180
0
  {
181
0
    free((void*)pNamedPipe->name);
182
0
    free(pNamedPipe);
183
0
    return INVALID_HANDLE_VALUE;
184
0
  }
185
186
0
  pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpFileName);
187
188
0
  if (!pNamedPipe->lpFilePath)
189
0
  {
190
0
    free((void*)pNamedPipe->lpFileName);
191
0
    free((void*)pNamedPipe->name);
192
0
    free(pNamedPipe);
193
0
    return INVALID_HANDLE_VALUE;
194
0
  }
195
196
0
  pNamedPipe->clientfd = socket(PF_LOCAL, SOCK_STREAM, 0);
197
0
  pNamedPipe->serverfd = -1;
198
0
  pNamedPipe->ServerMode = FALSE;
199
0
  s.sun_family = AF_UNIX;
200
0
  sprintf_s(s.sun_path, ARRAYSIZE(s.sun_path), "%s", pNamedPipe->lpFilePath);
201
0
  status = connect(pNamedPipe->clientfd, (struct sockaddr*)&s, sizeof(struct sockaddr_un));
202
0
  pNamedPipe->common.ops = &ops;
203
204
0
  if (status != 0)
205
0
  {
206
0
    close(pNamedPipe->clientfd);
207
0
    free((char*)pNamedPipe->name);
208
0
    free((char*)pNamedPipe->lpFileName);
209
0
    free((char*)pNamedPipe->lpFilePath);
210
0
    free(pNamedPipe);
211
0
    return INVALID_HANDLE_VALUE;
212
0
  }
213
214
0
  if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
215
0
  {
216
#if 0
217
    int flags = fcntl(pNamedPipe->clientfd, F_GETFL);
218
219
    if (flags != -1)
220
      fcntl(pNamedPipe->clientfd, F_SETFL, flags | O_NONBLOCK);
221
222
#endif
223
0
  }
224
225
0
  return hNamedPipe;
226
0
}
227
228
extern HANDLE_CREATOR* GetNamedPipeClientHandleCreator(void);
229
HANDLE_CREATOR* GetNamedPipeClientHandleCreator(void)
230
0
{
231
0
  _NamedPipeClientHandleCreator.IsHandled = IsNamedPipeFileNameA;
232
0
  _NamedPipeClientHandleCreator.CreateFileA = NamedPipeClientCreateFileA;
233
0
  return &_NamedPipeClientHandleCreator;
234
0
}
235
236
#endif
237
238
/* Extended API */
239
240
0
#define NAMED_PIPE_PREFIX_PATH "\\\\.\\pipe\\"
241
242
BOOL IsNamedPipeFileNameA(LPCSTR lpName)
243
0
{
244
0
  if (strncmp(lpName, NAMED_PIPE_PREFIX_PATH, sizeof(NAMED_PIPE_PREFIX_PATH) - 1) != 0)
245
0
    return FALSE;
246
247
0
  return TRUE;
248
0
}
249
250
char* GetNamedPipeNameWithoutPrefixA(LPCSTR lpName)
251
0
{
252
0
  char* lpFileName = NULL;
253
254
0
  if (!lpName)
255
0
    return NULL;
256
257
0
  if (!IsNamedPipeFileNameA(lpName))
258
0
    return NULL;
259
260
0
  lpFileName = _strdup(&lpName[strnlen(NAMED_PIPE_PREFIX_PATH, sizeof(NAMED_PIPE_PREFIX_PATH))]);
261
0
  return lpFileName;
262
0
}
263
264
char* GetNamedPipeUnixDomainSocketBaseFilePathA(void)
265
0
{
266
0
  char* lpTempPath = NULL;
267
0
  char* lpPipePath = NULL;
268
0
  lpTempPath = GetKnownPath(KNOWN_PATH_TEMP);
269
270
0
  if (!lpTempPath)
271
0
    return NULL;
272
273
0
  lpPipePath = GetCombinedPath(lpTempPath, ".pipe");
274
0
  free(lpTempPath);
275
0
  return lpPipePath;
276
0
}
277
278
char* GetNamedPipeUnixDomainSocketFilePathA(LPCSTR lpName)
279
0
{
280
0
  char* lpPipePath = NULL;
281
0
  char* lpFileName = NULL;
282
0
  char* lpFilePath = NULL;
283
0
  lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA();
284
0
  lpFileName = GetNamedPipeNameWithoutPrefixA(lpName);
285
0
  lpFilePath = GetCombinedPath(lpPipePath, (char*)lpFileName);
286
0
  free(lpPipePath);
287
0
  free(lpFileName);
288
0
  return lpFilePath;
289
0
}
290
291
int GetNamePipeFileDescriptor(HANDLE hNamedPipe)
292
0
{
293
0
#ifndef _WIN32
294
0
  int fd = 0;
295
0
  WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)hNamedPipe;
296
297
0
  if (!NamedPipeClientIsHandled(hNamedPipe))
298
0
    return -1;
299
300
0
  fd = (pNamedPipe->ServerMode) ? pNamedPipe->serverfd : pNamedPipe->clientfd;
301
0
  return fd;
302
#else
303
  return -1;
304
#endif
305
0
}