22#include <winpr/config.h>
25#include <winpr/path.h>
26#include <winpr/file.h>
28#ifdef WINPR_HAVE_UNISTD_H
33#define TAG WINPR_TAG("file")
40#include <sys/statvfs.h>
43#include "../handle/handle.h"
45#include "../pipe/pipe.h"
46#include "namedPipeClient.h"
48static BOOL NamedPipeClientIsHandled(HANDLE handle)
50 return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_NAMED_PIPE, TRUE);
53static BOOL NamedPipeClientCloseHandle(HANDLE handle)
55 WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)handle;
57 if (!NamedPipeClientIsHandled(handle))
60 if (pNamedPipe->clientfd != -1)
63 close(pNamedPipe->clientfd);
64 pNamedPipe->clientfd = -1;
67 if (pNamedPipe->serverfd != -1)
70 close(pNamedPipe->serverfd);
71 pNamedPipe->serverfd = -1;
74 if (pNamedPipe->pfnUnrefNamedPipe)
75 pNamedPipe->pfnUnrefNamedPipe(pNamedPipe);
77 free(pNamedPipe->lpFileName);
78 pNamedPipe->lpFileName =
nullptr;
79 free(pNamedPipe->lpFilePath);
80 pNamedPipe->lpFilePath =
nullptr;
81 free(pNamedPipe->name);
82 pNamedPipe->name =
nullptr;
86static int NamedPipeClientGetFd(HANDLE handle)
88 WINPR_NAMED_PIPE* file = (WINPR_NAMED_PIPE*)handle;
90 if (!NamedPipeClientIsHandled(handle))
94 return file->serverfd;
96 return file->clientfd;
100 NamedPipeClientIsHandled,
101 NamedPipeClientCloseHandle,
102 NamedPipeClientGetFd,
124static HANDLE NamedPipeClientCreateFileA(LPCSTR lpFileName, WINPR_ATTR_UNUSED DWORD dwDesiredAccess,
125 WINPR_ATTR_UNUSED DWORD dwShareMode,
126 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
127 WINPR_ATTR_UNUSED DWORD dwCreationDisposition,
128 DWORD dwFlagsAndAttributes,
129 WINPR_ATTR_UNUSED HANDLE hTemplateFile)
132 struct sockaddr_un s = WINPR_C_ARRAY_INIT;
134 if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
136 WLog_ERR(TAG,
"WinPR does not support the FILE_FLAG_OVERLAPPED flag");
137 SetLastError(ERROR_NOT_SUPPORTED);
138 return INVALID_HANDLE_VALUE;
142 return INVALID_HANDLE_VALUE;
144 if (!IsNamedPipeFileNameA(lpFileName))
145 return INVALID_HANDLE_VALUE;
147 WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)calloc(1,
sizeof(WINPR_NAMED_PIPE));
151 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
152 return INVALID_HANDLE_VALUE;
155 HANDLE hNamedPipe = (HANDLE)pNamedPipe;
156 WINPR_HANDLE_SET_TYPE_AND_MODE(pNamedPipe, HANDLE_TYPE_NAMED_PIPE, WINPR_FD_READ);
157 pNamedPipe->name = _strdup(lpFileName);
159 if (!pNamedPipe->name)
161 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
165 pNamedPipe->dwOpenMode = 0;
166 pNamedPipe->dwPipeMode = 0;
167 pNamedPipe->nMaxInstances = 0;
168 pNamedPipe->nOutBufferSize = 0;
169 pNamedPipe->nInBufferSize = 0;
170 pNamedPipe->nDefaultTimeOut = 0;
171 pNamedPipe->dwFlagsAndAttributes = dwFlagsAndAttributes;
172 pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpFileName);
174 if (!pNamedPipe->lpFileName)
177 pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpFileName);
179 if (!pNamedPipe->lpFilePath)
182 pNamedPipe->clientfd = socket(PF_LOCAL, SOCK_STREAM, 0);
183 if (pNamedPipe->clientfd < 0)
187 const BOOL inherit = lpSecurityAttributes && lpSecurityAttributes->bInheritHandle;
188 if (!winpr_set_cloexec(pNamedPipe->clientfd, !inherit))
192 pNamedPipe->serverfd = -1;
193 pNamedPipe->ServerMode = FALSE;
194 s.sun_family = AF_UNIX;
195 (void)sprintf_s(s.sun_path, ARRAYSIZE(s.sun_path),
"%s", pNamedPipe->lpFilePath);
196 status = connect(pNamedPipe->clientfd, (
struct sockaddr*)&s,
sizeof(
struct sockaddr_un));
197 pNamedPipe->common.ops = &ops;
202 if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
205 WLog_ERR(TAG,
"TODO: implement this");
213 if (pNamedPipe->clientfd >= 0)
214 close(pNamedPipe->clientfd);
215 free(pNamedPipe->name);
216 free(pNamedPipe->lpFileName);
217 free(pNamedPipe->lpFilePath);
220 return INVALID_HANDLE_VALUE;
225 static const HANDLE_CREATOR NamedPipeClientHandleCreator = { .IsHandled = IsNamedPipeFileNameA,
227 NamedPipeClientCreateFileA };
228 return &NamedPipeClientHandleCreator;
235#define NAMED_PIPE_PREFIX_PATH "\\\\.\\pipe\\"
237BOOL IsNamedPipeFileNameA(LPCSTR lpName)
239 return (strncmp(lpName, NAMED_PIPE_PREFIX_PATH,
sizeof(NAMED_PIPE_PREFIX_PATH) - 1) == 0);
242char* GetNamedPipeNameWithoutPrefixA(LPCSTR lpName)
244 char* lpFileName =
nullptr;
249 if (!IsNamedPipeFileNameA(lpName))
252 lpFileName = _strdup(&lpName[strnlen(NAMED_PIPE_PREFIX_PATH,
sizeof(NAMED_PIPE_PREFIX_PATH))]);
256char* GetNamedPipeUnixDomainSocketBaseFilePathA(
void)
258 char* lpTempPath =
nullptr;
259 char* lpPipePath =
nullptr;
260 lpTempPath = GetKnownPath(KNOWN_PATH_TEMP);
265 lpPipePath = GetCombinedPath(lpTempPath,
".pipe");
270char* GetNamedPipeUnixDomainSocketFilePathA(LPCSTR lpName)
272 char* lpPipePath =
nullptr;
273 char* lpFileName =
nullptr;
274 char* lpFilePath =
nullptr;
275 lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA();
276 lpFileName = GetNamedPipeNameWithoutPrefixA(lpName);
277 lpFilePath = GetCombinedPath(lpPipePath, lpFileName);
283int GetNamePipeFileDescriptor(HANDLE hNamedPipe)
287 WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)hNamedPipe;
289 if (!NamedPipeClientIsHandled(hNamedPipe))
292 fd = (pNamedPipe->ServerMode) ? pNamedPipe->serverfd : pNamedPipe->clientfd;